aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ic/src/ic_union_java.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ic/src/ic_union_java.erl')
-rw-r--r--lib/ic/src/ic_union_java.erl754
1 files changed, 754 insertions, 0 deletions
diff --git a/lib/ic/src/ic_union_java.erl b/lib/ic/src/ic_union_java.erl
new file mode 100644
index 0000000000..4be93f3c1f
--- /dev/null
+++ b/lib/ic/src/ic_union_java.erl
@@ -0,0 +1,754 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+
+-module(ic_union_java).
+
+-include("icforms.hrl").
+-include("ic.hrl").
+-include("ic_debug.hrl").
+%%-----------------------------------------------------------------
+%% External exports
+%%-----------------------------------------------------------------
+-export([gen/3]).
+
+%%-----------------------------------------------------------------
+%% Internal exports
+%%-----------------------------------------------------------------
+-export([]).
+
+%%-----------------------------------------------------------------
+%% External functions
+%%-----------------------------------------------------------------
+
+%%-----------------------------------------------------------------
+%% Func: gen/3
+%%-----------------------------------------------------------------
+gen(G, N, X) when is_record(X, union) ->
+
+ %% Create a TK value if not existed
+ %% Should be integrated in fetchTk
+ %% instead
+ NewX = case ic_forms:get_tk(X) of
+ undefined ->
+ S = ic_genobj:tktab(G),
+ Tk = ictype:tk(G, S, N, X),
+ #union{ id = X#union.id,
+ type = X#union.type,
+ body = X#union.body,
+ tk = Tk };
+ _Tk ->
+ X
+ end,
+
+ UnionName = ic_forms:get_java_id(NewX),
+ WiredUnionName = ic_forms:get_id2(NewX),
+ N2 = [UnionName ++ "Package"|N],
+ %%?PRINTDEBUG2("Recursive call over type ~p",
+ %% [[ic_forms:get_type(NewX)]]),
+ ic_jbe:gen(G, N, [ic_forms:get_type(NewX)]),
+ %%?PRINTDEBUG2("Recursive call over body: ~p",
+ %% [ic_forms:get_body(NewX)]),
+ ic_jbe:gen(G, N2, ic_forms:get_body(NewX)),
+
+ emit_union_class(G, N, NewX, UnionName),
+ emit_holder_class(G, N, NewX, UnionName),
+ emit_helper_class(G, N, NewX, UnionName, WiredUnionName);
+gen(_G, _N, _X) ->
+ ok.
+
+
+%%-----------------------------------------------------------------
+%% Internal functions
+%%-----------------------------------------------------------------
+
+%%-----------------------------------------------------------------
+%% Func: emit_union_class/4
+%%-----------------------------------------------------------------
+emit_union_class(G, N, X, UnionName) ->
+ {Fd, _} = ic_file:open_java_file(G, N, UnionName),
+
+ DiscrType = ic_java_type:getType(G, [UnionName ++ "Package"|N],
+ ic_forms:get_type(X)),
+
+ MList = union_member_list(G, N, X, DiscrType),
+
+ ic_codegen:emit(Fd, "final public class ~s {\n",[UnionName]),
+
+ ic_codegen:emit(Fd, " // instance variables\n", []),
+ ic_codegen:emit(Fd, " private boolean _initialized;\n", []),
+ ic_codegen:emit(Fd, " private ~s _discriminator;\n", [DiscrType]),
+ ic_codegen:emit(Fd, " private java.lang.Object _value;\n", []),
+
+ {tk_union,_, _,DiscrTk, _, _} = ic_forms:get_tk(X),
+
+ DV = get_default_val(G, [UnionName |N], DiscrType, DiscrTk, MList),
+
+ case DV of
+ none -> %% all values in case
+ ok;
+ _ ->
+ ic_codegen:emit(Fd, " private ~s _default = ~s;\n",
+ [DiscrType, DV])
+ end,
+
+ ic_codegen:nl(Fd),
+ ic_codegen:emit(Fd, " // constructors\n", []),
+
+ ic_codegen:emit(Fd, " public ~s() {\n", [UnionName]),
+ ic_codegen:emit(Fd, " _initialized = false;\n", []),
+ ic_codegen:emit(Fd, " _value = null;\n", []),
+ ic_codegen:emit(Fd, " }\n", []),
+ ic_codegen:nl(Fd),
+
+ ic_codegen:emit(Fd, " // discriminator access\n", []),
+
+ ic_codegen:emit(Fd, " public ~s discriminator() "
+ "throws java.lang.Exception {\n", [DiscrType]),
+ ic_codegen:emit(Fd, " if (!_initialized) {\n", []),
+ ic_codegen:emit(Fd, " throw new java.lang.Exception(\"\");\n",[]),
+ ic_codegen:emit(Fd, " }\n", []),
+ ic_codegen:emit(Fd, " return _discriminator;\n", []),
+ ic_codegen:emit(Fd, " }\n", []),
+ ic_codegen:nl(Fd),
+
+ emit_union_members_functions(G, [UnionName ++ "Package"|N], X,
+ Fd, UnionName, DiscrType, MList, MList),
+ ic_codegen:nl(Fd),
+
+ ic_codegen:emit(Fd, "}\n", []),
+ file:close(Fd).
+
+%%-----------------------------------------------------------------
+%% Func: emit_holder_class/4
+%%-----------------------------------------------------------------
+emit_holder_class(G, N, _X, UnionName) ->
+ UName = string:concat(UnionName, "Holder"),
+ {Fd, _} = ic_file:open_java_file(G, N, UName),
+
+ ic_codegen:emit(Fd, "final public class ~sHolder {\n",[UnionName]),
+
+ ic_codegen:emit(Fd, " // instance variables\n"),
+ ic_codegen:emit(Fd, " public ~s value;\n", [UnionName]),
+ ic_codegen:nl(Fd),
+
+ ic_codegen:emit(Fd, " // constructors\n"),
+ ic_codegen:emit(Fd, " public ~sHolder() {}\n", [UnionName]),
+ ic_codegen:emit(Fd, " public ~sHolder(~s initial) {\n",
+ [UnionName, UnionName]),
+ ic_codegen:emit(Fd, " value = initial;\n"),
+ ic_codegen:emit(Fd, " }\n"),
+ ic_codegen:nl(Fd),
+
+ ic_codegen:emit(Fd, " // methods\n"),
+
+ ic_codegen:emit(Fd, " public void _marshal(~sOtpOutputStream out) throws java.lang.Exception {\n",
+ [?ERLANGPACKAGE]),
+ ic_codegen:emit(Fd, " ~sHelper.marshal(out, value);\n", [UnionName]),
+ ic_codegen:emit(Fd, " }\n\n"),
+
+ ic_codegen:emit(Fd, " public void _unmarshal(~sOtpInputStream in) throws java.lang.Exception {\n",
+ [?ERLANGPACKAGE]),
+ ic_codegen:emit(Fd, " value = ~sHelper.unmarshal(in);\n", [UnionName]),
+ ic_codegen:emit(Fd, " }\n\n"),
+
+ ic_codegen:emit(Fd, "}\n"),
+ file:close(Fd).
+
+
+%%-----------------------------------------------------------------
+%% Func: emit_helper_class/4
+%%-----------------------------------------------------------------
+emit_helper_class(G, N, X, UnionName, WiredUnionName) ->
+ UName = string:concat(UnionName, "Helper"),
+ {Fd, _} = ic_file:open_java_file(G, N, UName),
+
+ DiscrType = ic_java_type:getType(G, [ UnionName ++ "Package" |N],
+ ic_forms:get_type(X)),
+
+ ic_codegen:emit(Fd, "public class ~sHelper {\n",[UnionName]),
+
+ ic_codegen:emit(Fd, " // constructors\n", []),
+ ic_codegen:emit(Fd, " private ~sHelper() {}\n", [UnionName]),
+ ic_codegen:nl(Fd),
+
+ ic_codegen:emit(Fd, " // methods\n", []),
+ MList = union_member_list(G, N, X, DiscrType),
+
+ ic_codegen:emit(Fd, " public static void marshal(~sOtpOutputStream _out, ~s _value)\n",
+ [?ERLANGPACKAGE, UnionName]),
+ ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
+ emit_union_marshal_function(G, N, X, Fd, UnionName, WiredUnionName, MList),
+ ic_codegen:emit(Fd, " }\n\n"),
+
+ ic_codegen:emit(Fd, " public static ~s unmarshal(~sOtpInputStream _in)\n",
+ [UnionName, ?ERLANGPACKAGE]),
+ ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
+ emit_union_unmarshal_function(G, N, X, Fd, UnionName, WiredUnionName, MList),
+ ic_codegen:emit(Fd, " }\n\n"),
+
+ ic_codegen:emit(Fd, " public static String id() {\n"),
+ ic_codegen:emit(Fd, " return ~p;\n",[ictk:get_IR_ID(G, N, X)]),
+ ic_codegen:emit(Fd, " }\n\n"),
+
+ ic_codegen:emit(Fd, " public static String name() {\n"),
+ ic_codegen:emit(Fd, " return ~p;\n",[UnionName]),
+ ic_codegen:emit(Fd, " }\n\n"),
+
+ ic_jbe:emit_type_function(G, N, X, Fd),
+
+
+ ic_codegen:emit(Fd, " public static void insert(~sAny _any, ~s _this)\n",
+ [?ICPACKAGE,UnionName]),
+ ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
+
+ ic_codegen:emit(Fd, " ~sOtpOutputStream _os = \n",[?ERLANGPACKAGE]),
+ ic_codegen:emit(Fd, " new ~sOtpOutputStream();\n\n",[?ERLANGPACKAGE]),
+
+ ic_codegen:emit(Fd, " _any.type(type());\n"),
+ ic_codegen:emit(Fd, " marshal(_os, _this);\n"),
+ ic_codegen:emit(Fd, " _any.insert_Streamable(_os);\n"),
+ ic_codegen:emit(Fd, " }\n\n"),
+
+ ic_codegen:emit(Fd, " public static ~s extract(~sAny _any)\n",
+ [UnionName,?ICPACKAGE]),
+ ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
+
+ ic_codegen:emit(Fd, " return unmarshal(_any.extract_Streamable());\n"),
+ ic_codegen:emit(Fd, " }\n\n"),
+
+ ic_codegen:emit(Fd, " public static int discriminatorAsInt(~s _discriminator)\n",
+ [DiscrType]),
+ ic_codegen:emit(Fd, " throws java.lang.Exception {\n"),
+ emit_discriminator_as_int(G, N, ic_forms:get_type(X), Fd),
+ ic_codegen:emit(Fd, " }\n\n"),
+
+ ic_codegen:emit(Fd, "}\n"),
+ file:close(Fd).
+
+%%-----------------------------------------------------------------
+%% Func: emit_union_members_functions/7
+%%-----------------------------------------------------------------
+emit_union_members_functions(_, _, _, _, _, _, [], _) ->
+ ok;
+emit_union_members_functions(G, N, X, Fd, UnionName, DiscrType,
+ [{Label, Case, TypeDef, Id, Ls} | MList], MListTot) ->
+
+ CaseId = Case#case_dcl.id, %% Maybe Array
+ CaseType = Case#case_dcl.type, %% Maybe Sequence
+
+ Type = if element(1,CaseId) == array ->
+ ic_java_type:getType(G, N, TypeDef) ++
+ ic_java_type:getdim(CaseId#array.size);
+ true ->
+ ic_java_type:getType(G, N, TypeDef)
+ end,
+
+ HolderType =
+ if element(1,CaseId) == array ->
+ ic_java_type:getHolderType(G, N, CaseId);
+ true ->
+ if element(1,CaseType) == sequence ->
+ ic_util:to_dot(G,[Id|N]) ++"Holder";
+ true ->
+ ic_java_type:getHolderType(G, N, TypeDef)
+ end
+ end,
+
+ %%
+ %% Set method
+ %%
+ ic_codegen:emit(Fd, " // ~s access and set functions\n",[Id]),
+ ic_codegen:emit(Fd, " public void ~s(~s value) "
+ "throws java.lang.Exception {\n",
+ [Id, Type]),
+ ic_codegen:emit(Fd, " _initialized = true;\n", []),
+ case Label of
+ "default" ->
+ ic_codegen:emit(Fd, " _discriminator = (~s) _default;\n",
+ [DiscrType]);
+ _ ->
+ case ic_java_type:isBasicType(G, N, ic_forms:get_type(X)) of
+ true ->
+ ic_codegen:emit(Fd, " _discriminator = (~s) "
+ "~s;\n",
+ [DiscrType, Label]);
+ _ ->
+ ic_codegen:emit(Fd, " _discriminator = (~s) "
+ "~s.~s;\n",
+ [DiscrType, DiscrType, Label])
+ end
+ end,
+ ic_codegen:emit(Fd, " _value = new ~s(value);\n",
+ [HolderType]),
+ ic_codegen:emit(Fd, " }\n", []),
+
+ %%
+ %% Check this entry has more than one label and the generate an extra set method.
+ %%
+ case Ls of
+ [] ->
+ ok;
+ _ ->
+ ic_codegen:emit(Fd, " public void ~s(~s discriminator, ~s value) "
+ "throws java.lang.Exception {\n",
+ [Id, DiscrType, Type]),
+ ic_codegen:emit(Fd, " _initialized = true;\n", []),
+ ic_codegen:emit(Fd, " _discriminator = (~s) discriminator;\n",
+ [DiscrType]),
+ ic_codegen:emit(Fd, " _value = new ~s(value);\n",
+ [HolderType]),
+ ic_codegen:emit(Fd, " }\n", [])
+ end,
+
+ %%
+ %% Get method
+ %%
+ ic_codegen:emit(Fd, " public ~s ~s() throws java.lang.Exception {\n",
+ [Type, Id]),
+ ic_codegen:emit(Fd, " if (!_initialized) {\n", []),
+ ic_codegen:emit(Fd, " throw new java.lang.Exception(\"\");\n",[]),
+ ic_codegen:emit(Fd, " }\n", []),
+ ic_codegen:emit(Fd, " switch (~sHelper.discriminatorAsInt"
+ "(discriminator())) {\n",
+ [UnionName]),
+ if
+ Label == "default" ->
+ ic_codegen:emit(Fd, " default:\n", []),
+ ic_codegen:emit(Fd, " break;\n", []),
+ emit_default_access_fun_switch_cases(G, N, X, Fd, DiscrType,
+ MListTot),
+ ic_codegen:emit(Fd, " throw new java.lang.Exception(\"\");\n", []);
+ true ->
+ ic_codegen:emit(Fd, " case ~s:\n",
+ [get_case_as_int(G, N, ic_forms:get_type(X),
+ DiscrType, Label)]),
+ ic_codegen:emit(Fd, " break;\n", []),
+ ic_codegen:emit(Fd, " default:\n", []),
+ ic_codegen:emit(Fd, " throw new java.lang.Exception(\"\");\n", [])
+ end,
+ ic_codegen:emit(Fd, " }\n", []),
+
+ ic_codegen:emit(Fd, " return ((~s) _value).value;\n",
+ [HolderType]),
+ ic_codegen:emit(Fd, " }\n", []),
+ ic_codegen:nl(Fd),
+ emit_union_members_functions(G, N, X, Fd, UnionName, DiscrType, MList,
+ MListTot).
+
+
+%%-----------------------------------------------------------------
+%% Func: emit_default_access_fun_switch_cases/6
+%%-----------------------------------------------------------------
+emit_default_access_fun_switch_cases(_G, _N, _X, _Fd, _DiscrType, []) ->
+ ok;
+emit_default_access_fun_switch_cases(G, N, X, Fd, DiscrType,
+ [{"default", _, _, _, _} |MList]) ->
+ emit_default_access_fun_switch_cases(G, N, X, Fd, DiscrType, MList);
+emit_default_access_fun_switch_cases(G, N, X, Fd, DiscrType,
+ [{Label, _Case, _TypeDef, _Id, _} | MList]) ->
+ ic_codegen:emit(Fd, " case ~s:\n",
+ [get_case_as_int(G, N, ic_forms:get_type(X),
+ DiscrType, Label)]),
+ emit_default_access_fun_switch_cases(G, N, X, Fd, DiscrType, MList).
+
+
+
+%%-----------------------------------------------------------------
+%% Func: emit_union_unmarshal_function/5
+%%-----------------------------------------------------------------
+emit_union_unmarshal_function(G, N, X, Fd, UnionName, WiredUnionName, MList) ->
+ DiscrTypeForm = ic_forms:get_type(X),
+ DiscrType = ic_java_type:getType(G, [UnionName ++ "Package"|N],
+ DiscrTypeForm),
+
+ ic_codegen:emit(Fd, " _in.read_tuple_head();\n\n"),
+
+ ic_codegen:emit(Fd, " if ((_in.read_atom()).compareTo(~p) != 0)\n",
+ [ic_util:to_undersc([WiredUnionName|N])]),
+ ic_codegen:emit(Fd, " throw new java.lang.Exception(\"\");\n\n",[]),
+
+ ic_codegen:emit(Fd, " ~s _value = new ~s();\n", [UnionName, UnionName]),
+
+ %% Decode discriminator
+ case ic_java_type:isBasicType(G, N, DiscrTypeForm) of
+ true ->
+ ic_codegen:emit(Fd, " ~s _discriminator = _in~s;\n\n",
+ [DiscrType,
+ ic_java_type:unMarshalFun(G, N, X, DiscrTypeForm)]);
+ _ ->
+ ic_codegen:emit(Fd, " ~s _discriminator = ~s.unmarshal(_in);\n\n",
+ [DiscrType,ic_java_type:getUnmarshalType(G, N, X, DiscrTypeForm)])
+ end,
+
+ ic_codegen:emit(Fd, " switch (~sHelper.discriminatorAsInt(_discriminator)) {\n",
+ [UnionName]),
+
+ emit_union_unmarshal_function_loop(G, [UnionName ++ "Package"|N], X,
+ Fd, DiscrType, MList),
+
+ ic_codegen:emit(Fd, " }\n\n"),
+
+ ic_codegen:emit(Fd, " return _value;\n").
+
+%%-----------------------------------------------------------------
+%% Func: emit_union_unmarshal_function_loop/6
+%%-----------------------------------------------------------------
+emit_union_unmarshal_function_loop(_, _, _, _, _, []) ->
+ ok;
+emit_union_unmarshal_function_loop(G, N, X, Fd, DiscrType,
+ [{Label, Case, Type, Id, Ls} |MList]) ->
+ case Label of
+ "default" ->
+ ic_codegen:emit(Fd, " default:\n");
+ _ ->
+ ic_codegen:emit(Fd, " case ~s:\n",
+ [get_case_as_int(G, N, ic_forms:get_type(X),
+ DiscrType, Label)])
+ end,
+
+ gen_multiple_cases(G, N, X, Fd, DiscrType, Ls),
+
+ CaseId = Case#case_dcl.id, %% Maybe Array
+ CaseType = Case#case_dcl.type, %% Maybe Sequence
+
+ case element(1,CaseId) of
+ array ->
+ ic_codegen:emit(Fd, " _value.~s(~s.unmarshal(_in));\n",
+ [Id,
+ ic_java_type:getUnmarshalType(G, N, Case, CaseId)]);
+
+ _ ->
+ case element(1, CaseType) of
+ sequence ->
+ ic_codegen:emit(Fd, " _value.~s(~s.unmarshal(_in));\n",
+ [Id,
+ ic_java_type:getUnmarshalType(G, N, Case, CaseType)]);
+ _ ->
+ case ic_java_type:isBasicType(G, N, CaseType) of
+ true ->
+ ic_codegen:emit(Fd, " _value.~s(_in~s);\n",
+ [Id,
+ ic_java_type:unMarshalFun(G, N, X, Type)]);
+ false ->
+ ic_codegen:emit(Fd, " _value.~s(~s.unmarshal(_in));\n",
+ [Id,
+ ic_java_type:getUnmarshalType(G, N, X, Type)])
+ end
+ end
+ end,
+
+ ic_codegen:emit(Fd, " break;\n", []),
+ emit_union_unmarshal_function_loop(G, N, X, Fd, DiscrType, MList).
+
+
+
+
+
+%%-----------------------------------------------------------------
+%% Func: emit_union_marshal_function/6
+%%-----------------------------------------------------------------
+emit_union_marshal_function(G, N, X, Fd, UnionName, WiredUnionName, MList) ->
+
+ DiscrTypeForm = ic_forms:get_type(X),
+ DiscrType = ic_java_type:getType(G, [UnionName ++ "Package" |N],
+ DiscrTypeForm),
+
+ ic_codegen:emit(Fd, " _out.write_tuple_head(3);\n"),
+ ic_codegen:emit(Fd, " _out.write_atom(~p);\n",
+ [ic_util:to_undersc([WiredUnionName|N])]),
+
+ case ic_java_type:isBasicType(G, N, DiscrTypeForm) of
+ true ->
+ ic_codegen:emit(Fd, " _out~s(_value.discriminator());\n\n",
+ [ic_java_type:marshalFun(G, N, X, DiscrTypeForm)]);
+ false ->
+ ic_codegen:emit(Fd, " ~s(_out, _value.discriminator());\n\n",
+ [ic_java_type:marshalFun(G, N, X, DiscrTypeForm)])
+ end,
+
+ ic_codegen:emit(Fd, " switch(~sHelper.discriminatorAsInt(_value.discriminator())) {\n",
+ [UnionName]),
+
+ emit_union_marshal_function_loop(G,
+ [ UnionName ++ "Package"|N],
+ X,
+ Fd,
+ DiscrType,
+ MList),
+
+ ic_codegen:emit(Fd, " }\n\n", []).
+
+
+%%-----------------------------------------------------------------
+%% Func: emit_union_marshal_function_loop/
+%%-----------------------------------------------------------------
+emit_union_marshal_function_loop(_, _, _, _, _, []) ->
+ ok;
+emit_union_marshal_function_loop(G, N, X, Fd, DiscrType,
+ [{Label, Case, Type, Id, Ls} |MList]) ->
+ case Label of
+ "default" ->
+ ic_codegen:emit(Fd, " default:\n",
+ []);
+ _ ->
+ ic_codegen:emit(Fd, " case ~s:\n",
+ [get_case_as_int(G, N, ic_forms:get_type(X),
+ DiscrType, Label)])
+ end,
+
+ gen_multiple_cases(G, N, X, Fd, DiscrType, Ls),
+
+
+ CaseId = Case#case_dcl.id, %% Maybe Array
+ CaseType = Case#case_dcl.type, %% Maybe Sequence
+
+ case element(1,CaseId) of
+ array ->
+ ic_codegen:emit(Fd, " ~s(_out, _value.~s());\n",
+ [ic_java_type:marshalFun(G, N, Case, CaseId),
+ Id]);
+ _ ->
+ case element(1, CaseType) of
+ sequence ->
+ ic_codegen:emit(Fd, " ~s.marshal(_out, _value.~s());\n",
+ [ic_util:to_dot(G,[Id|N]) ++ "Helper",
+ Id]);
+ _ ->
+ case ic_java_type:isBasicType(G, N, CaseType) of
+ true ->
+ ic_codegen:emit(Fd, " _out~s(_value.~s());\n",
+ [ic_java_type:marshalFun(G, N, X, Type),
+ Id]);
+ false ->
+ ic_codegen:emit(Fd, " ~s(_out, _value.~s());\n",
+ [ic_java_type:marshalFun(G, N, X, Type),
+ Id])
+ end
+ end
+ end,
+
+ ic_codegen:emit(Fd, " break;\n", []),
+ emit_union_marshal_function_loop(G, N, X, Fd, DiscrType, MList).
+
+
+
+gen_multiple_cases(_G, _N, _X, _Fd, _DiscrType, []) ->
+ ok;
+gen_multiple_cases(G, N, X, Fd, DiscrType, [Label |Ls]) ->
+ ic_codegen:emit(Fd, " case ~s:\n",
+ [get_case_as_int(G, N, ic_forms:get_type(X),
+ DiscrType, getLabel(DiscrType, Label))]),
+ gen_multiple_cases(G, N, X, Fd, DiscrType, Ls).
+
+
+%%-----------------------------------------------------------------
+%% Func: union_member_list/3
+%%-----------------------------------------------------------------
+union_member_list(G, N, X, DiscrType) ->
+ M = lists:map(
+ fun(Case) ->
+ {Label, LabelList} = case check_default(ic_forms:get_idlist(Case)) of
+ {{default, C}, List} ->
+ {{default, C}, List};
+ {L, []} ->
+ {L, []};
+ {_, [L |Ls]} ->
+ {L, Ls}
+ end,
+
+ CName = ic_forms:get_java_id(Case),
+ CId = Case#case_dcl.id,
+ CType = Case#case_dcl.type,
+
+ if element(1,CId) == array ->
+ N2 = [ic_forms:get_id2(X) ++ "Package" |N],
+ ic_array_java:gen(G, N2, Case, CId);
+ true ->
+ if element(1,Case#case_dcl.type) == sequence ->
+ N2 = [ic_forms:get_id2(X) ++ "Package" |N],
+ ic_sequence_java:gen(G, N2, CType, CName);
+ true ->
+ ok
+ end
+ end,
+
+ {getLabel(DiscrType, Label),
+ Case,
+ ic_forms:get_type(Case),
+ CName,
+ LabelList}
+ end,
+ ic_forms:get_body(X)),
+ lists:flatten(M).
+
+check_default([]) ->
+ {false, []};
+check_default([{default, X} |Ls]) ->
+ {{default, X}, Ls};
+check_default([L]) ->
+ {false, [L]};
+check_default([L |Ls]) ->
+ {X, Y} = check_default(Ls),
+ {X, [L | Y]}.
+
+getLabel(_, {'<integer_literal>', _, N}) ->
+ N;
+getLabel(_, {'<character_literal>', _, N}) ->
+ "'" ++ N ++ "'";
+getLabel(_, {'<wcharacter_literal>', _, N}) ->
+ "'" ++ N ++ "'";
+getLabel(_, {'TRUE',_}) ->
+ "true";
+getLabel(_, {'FALSE',_}) ->
+ "true";
+getLabel(_, {default, _}) ->
+ "default";
+getLabel(_DiscrType, X) -> %%DiscrType ++ "." ++
+ ic_util:to_dot(ic_forms:get_id(X)).
+
+get_default_val(G, N, _, tk_short, MList) ->
+ integer_default_val(G, N, 1, lists:map(fun({V, _, _, _, _}) -> V end, MList));
+get_default_val(G, N, _, tk_long, MList) ->
+ integer_default_val(G, N, 1, lists:map(fun({V, _, _, _, _}) -> V end, MList));
+get_default_val(G, N, _, tk_ushort, MList) ->
+ integer_default_val(G, N, 1, lists:map(fun({V, _, _, _, _}) -> V end, MList));
+get_default_val(G, N, _, tk_ulong, MList) ->
+ integer_default_val(G, N, 1, lists:map(fun({V, _, _, _, _}) -> V end, MList));
+get_default_val(G, N, _, tk_char, MList) ->
+ char_default_val(G, N, $a, lists:map(fun({V, _, _, _, _}) -> V end, MList));
+get_default_val(G, N, _, tk_boolean, MList) ->
+ boolean_default_val(G, N, lists:map(fun({V, _, _, _, _}) -> V end, MList));
+get_default_val(G, N, DiscrType, {tk_enum, _, _, Values}, MList) ->
+ enum_default_val(G, N, DiscrType, Values, MList).
+
+integer_default_val(G, N, Num, MList) ->
+ Num2 = integer_to_list(Num),
+ case lists:member(Num2, MList) of
+ true ->
+ integer_default_val(G, N, Num + 1, MList);
+ false ->
+ Num2
+ end.
+
+char_default_val(G, N, CharNum, MList) ->
+ Str = "'",
+ CharNum2 = Str ++ [CharNum | Str],
+ case lists:member(CharNum2, MList) of
+ true ->
+ char_default_val(G, N, CharNum + 1, MList);
+ false ->
+ CharNum2
+ end.
+
+boolean_default_val(G, N, MList) ->
+ if
+ length(MList) > 2 ->
+ ic_error:error(G, {plain_error_string,
+ lists:flatten(
+ io_lib:format("Default value found while all values have label on ~s",
+ [ic_util:to_colon(N)]))}),
+ none;
+ true ->
+ case MList of
+ ["true"] ->
+ "false";
+ ["false"] ->
+ "true";
+ ["default","true"] ->
+ "false";
+ ["true","default"] ->
+ "false";
+ ["default","false"] ->
+ "true";
+ ["false","default"] ->
+ "true";
+ _ ->
+ none
+ end
+ end.
+
+
+
+
+enum_default_val(G, N, DiscrType, Values, Mlist) ->
+
+ VLen = length(Values),
+ MLen = length(Mlist),
+
+ case MLen > VLen of
+ true ->
+ ic_error:error(G, {plain_error_string,
+ lists:flatten(
+ io_lib:format("Default value found while all values have label on ~s",
+ [ic_util:to_colon(N)]))}),
+ none;
+ false ->
+ enum_default_val_loop(G, N, DiscrType, Values, Mlist)
+ end.
+
+enum_default_val_loop(_G, _N, _, [], []) ->
+ none;
+enum_default_val_loop(_G, _N, DiscrType, [Value| _], []) ->
+ DiscrType ++ "." ++ Value;
+enum_default_val_loop(G, N, DiscrType, Values, [Case | MList]) when is_tuple(Case) ->
+ NewValues = lists:delete(element(1,Case), Values),
+ enum_default_val_loop(G, N, DiscrType, NewValues, MList).
+
+
+
+emit_discriminator_as_int(G, N, T, Fd) ->
+ case ictype:isBoolean(G,N,T) of
+ true ->
+ ic_codegen:emit(Fd, " if(_discriminator)\n", []),
+ ic_codegen:emit(Fd, " return 1;\n", []),
+ ic_codegen:emit(Fd, " else\n", []),
+ ic_codegen:emit(Fd, " return 0;\n", []);
+ false ->
+ case ictype:isEnum(G, N, T) of
+ true ->
+ ic_codegen:emit(Fd, " return _discriminator.value();\n",
+ []);
+ false ->
+ ic_codegen:emit(Fd, " return _discriminator;\n", [])
+ end
+ end.
+
+
+get_case_as_int(G, N, T, DiscrJavaTypeName, Label) ->
+ case ictype:isBoolean(G,N,T) of
+ true ->
+ case Label of
+ "true" ->
+ "1";
+ "false" ->
+ "0"
+ end;
+ false ->
+ case ictype:isEnum(G, N, T) of
+ true ->
+ DiscrJavaTypeName ++ "._" ++ Label;
+ false ->
+ "(" ++ DiscrJavaTypeName ++ ") " ++ Label
+ end
+ end.
+
+
+