diff options
Diffstat (limited to 'lib/ic/src/ic_union_java.erl')
-rw-r--r-- | lib/ic/src/ic_union_java.erl | 754 |
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. + + + |