diff options
Diffstat (limited to 'lib/ic/src/ic_enum_java.erl')
-rw-r--r-- | lib/ic/src/ic_enum_java.erl | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/lib/ic/src/ic_enum_java.erl b/lib/ic/src/ic_enum_java.erl new file mode 100644 index 0000000000..5978c3468e --- /dev/null +++ b/lib/ic/src/ic_enum_java.erl @@ -0,0 +1,312 @@ +%% +%% %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_enum_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, enum) -> + %%?PRINTDEBUG2("enum: ~p", [X]), + EnumName = ic_forms:get_java_id(X), + N2 = ["_" ++ EnumName |N], + ic_jbe:gen(G, N2, ic_forms:get_body(X)), + + emit_enum_class(G, N, X, EnumName), + emit_holder_class(G, N, X, EnumName), + emit_helper_class(G, N, X, EnumName); +gen(_G, _N, _X) -> + ok. + + +%%----------------------------------------------------------------- +%% Internal functions +%%----------------------------------------------------------------- + +%%----------------------------------------------------------------- +%% Func: emit_enum_class/4 +%%----------------------------------------------------------------- +emit_enum_class(G, N, X, EnumName) -> + {Fd, _} = ic_file:open_java_file(G, N, EnumName), + + EList = enum_member_name_list(G, N, X), + %%?PRINTDEBUG2("EList: ~p", [EList]), + ic_codegen:emit(Fd, ["final public class ",EnumName," {\n\n" + + " // instance variables\n"]), + + emit_enum_member_int_values_initialization(G, N, X, Fd, EList), + emit_enum_public_instance_variables(G, N, X, Fd, EnumName, EList), + + ic_codegen:emit(Fd, [" private int _value;\n\n" + + " // constructors\n" + " private ",EnumName,"(int __value) {\n" + " _value = __value;\n" + " }\n\n" + + " // methods\n" + " public int value() {\n" + " return _value;\n" + " }\n"]), + + emit_enum_from_int_function(G, N, X, Fd, EnumName, EList), + + ic_codegen:emit(Fd, "\n}\n"), + file:close(Fd). + +%%----------------------------------------------------------------- +%% Func: emit_holder_class/4 +%%----------------------------------------------------------------- +emit_holder_class(G, N, _X, EnumName) -> + EName = string:concat(EnumName, "Holder"), + {Fd, _} = ic_file:open_java_file(G, N, EName), + + ic_codegen:emit(Fd, ["final public class ",EnumName,"Holder {\n\n" + + " // instance variables\n" + " public ",EnumName," value;\n\n" + + " // constructors\n" + " public ",EnumName,"Holder() {}\n\n" + + " public ",EnumName,"Holder(",EnumName," initial) {\n" + " value = initial;\n" + " }\n\n" + + " // methods\n" + " public void _marshal(",?ERLANGPACKAGE,"OtpOutputStream out) throws java.lang.Exception {\n" + " ",EnumName,"Helper.marshal(out, value);\n" + " }\n\n" + + " public void _unmarshal(",?ERLANGPACKAGE,"OtpInputStream in) throws java.lang.Exception {\n" + " value = ",EnumName,"Helper.unmarshal(in);\n" + " }\n\n" + "}\n"]), + file:close(Fd). + + +%%----------------------------------------------------------------- +%% Func: emit_helper_class/4 +%%----------------------------------------------------------------- +emit_helper_class(G, N, X, EnumName) -> + EName = string:concat(EnumName, "Helper"), + WEList = enum_member_atom_list(G, N, X), + {Fd, _} = ic_file:open_java_file(G, N, EName), + + ic_codegen:emit(Fd, ["public class ",EnumName,"Helper {\n\n" + + " // constructors\n" + " private ",EnumName,"Helper() {}\n\n" + + " // methods\n" + + " public static void marshal(",?ERLANGPACKAGE,"OtpOutputStream _out, ",EnumName," _value)\n" + " throws java.lang.Exception {\n\n"]), + + emit_enum_write_function(G, N, X, Fd, EnumName), + + ic_codegen:emit(Fd, [" }\n\n" + + " public static ",EnumName," unmarshal(",?ERLANGPACKAGE,"OtpInputStream _in)\n" + " throws java.lang.Exception {\n\n"]), + + emit_enum_read_function(G, N, X, Fd, EnumName), + + ic_codegen:emit(Fd, "\n }\n\n"), + + emit_enum_private_member_variables(Fd, WEList), + + ic_codegen:emit(Fd, ["\n // Get integer value of enum from string\n" + " private static int _getIntFromName(String name) throws java.lang.Exception {\n" + " for(int i = 0; i < _memberCount; i++) {\n" + " if (name.equals(_members[i]))\n" + " return i;\n" + " }\n" + " throw new java.lang.Exception(\"\");\n" + " }\n\n" + + " public static String id() {\n" + " return \"",ictk:get_IR_ID(G, N, X),"\";\n" + " }\n\n" + + " public static String name() {\n" + " return \"",EnumName,"\";\n" + " }\n\n"]), + + ic_jbe:emit_type_function(G, N, X, Fd), + + ic_codegen:emit(Fd, [" public static void insert(",?ICPACKAGE,"Any _any, ",EnumName," _this)\n" + " throws java.lang.Exception {\n\n" + + " ",?ERLANGPACKAGE,"OtpOutputStream _os = \n" + " new ",?ERLANGPACKAGE,"OtpOutputStream();\n\n" + + " _any.type(type());\n" + " marshal(_os, _this);\n" + " _any.insert_Streamable(_os);\n" + " }\n\n" + + " public static ",EnumName," extract(",?ICPACKAGE,"Any _any)\n" + " throws java.lang.Exception {\n\n" + + " return unmarshal(_any.extract_Streamable());\n" + " }\n\n" + + "}\n"]), + file:close(Fd). + +%%----------------------------------------------------------------- +%% Func: emit_enum_public_instance_variables/6 +%%----------------------------------------------------------------- +emit_enum_public_instance_variables(_G, _N, _X, _Fd, _EnumName, []) -> + ok; +emit_enum_public_instance_variables(G, N, X, Fd, EnumName, [Enumerator |EList]) -> + ic_codegen:emit(Fd, [" public static final ",EnumName," ",Enumerator," = new ",EnumName,"(_",Enumerator,");\n"]), + emit_enum_public_instance_variables(G, N, X, Fd, EnumName, EList). + +%%----------------------------------------------------------------- +%% Func: emit_enum_member_int_values_initialization/5 +%%----------------------------------------------------------------- +emit_enum_member_int_values_initialization(G, N, X, Fd, EList) -> + InitString = emit_enum_member_int_values_initialization_1(G, N, X, Fd, EList, 0), + ic_codegen:emit(Fd, [" public static final int ",InitString,";\n"]). + + +%%----------------------------------------------------------------- +%% Func: emit_enum_member_int_values_initialization_1/6 +%%----------------------------------------------------------------- +emit_enum_member_int_values_initialization_1(_G, _N, _X, _Fd, [Enumerator], Num) -> + " _" ++ Enumerator ++ " = " ++ ic_util:to_list(Num); +emit_enum_member_int_values_initialization_1(G, N, X, Fd, [Enumerator |EList], Num) -> + Spaces = if + Num == 0 -> + ""; + true -> + " " + end, + Spaces ++ "_" ++ Enumerator ++ " = " ++ ic_util:to_list(Num) ++ ",\n" ++ + emit_enum_member_int_values_initialization_1(G, N, X, Fd, EList, Num + 1). + +%%----------------------------------------------------------------- +%% Func: emit_enum_from_int_function/6 +%%----------------------------------------------------------------- +emit_enum_from_int_function(_G, _N, _X, Fd, EnumName, EList) -> + ic_codegen:emit(Fd, + [" public static final ",EnumName," from_int(int __value) throws java.lang.Exception {\n" + " switch (__value) {\n"]), + emit_enum_from_int_function_switchbody(Fd, EList), + ic_codegen:emit(Fd, [" }\n" + " }\n"]). + +%%----------------------------------------------------------------- +%% Func: emit_enum_from_int_function_switchbody/2 +%%----------------------------------------------------------------- +emit_enum_from_int_function_switchbody(Fd, []) -> + ic_codegen:emit(Fd, [" default:\n" + " throw new java.lang.Exception(\"\");\n"]); +emit_enum_from_int_function_switchbody(Fd, [Enumerator |EList]) -> + ic_codegen:emit(Fd, [" case _",Enumerator,":\n" + " return ",Enumerator,";\n"]), + emit_enum_from_int_function_switchbody(Fd, EList). + +%%----------------------------------------------------------------- +%% Func: emit_enum_private_member_variables/2 +%%----------------------------------------------------------------- +emit_enum_private_member_variables(Fd, EList) -> + ic_codegen:emit(Fd, [" private static final int _memberCount = ",integer_to_list(length(EList)),";\n" + " private static String[] _members = {\n"]), + emit_enum_private_member_variables_1(Fd, EList), + ic_codegen:emit(Fd, " };\n"). + +%%----------------------------------------------------------------- +%% Func: emit_enum_private_member_variables_1/2 +%%----------------------------------------------------------------- +emit_enum_private_member_variables_1(Fd, [Enumerator]) -> + ic_codegen:emit(Fd, [" \"",Enumerator,"\"\n"]); +emit_enum_private_member_variables_1(Fd, [Enumerator |EList]) -> + ic_codegen:emit(Fd, [" \"",Enumerator,"\",\n"]), + emit_enum_private_member_variables_1(Fd, EList). + +%%----------------------------------------------------------------- +%% Func: emit_enum_read_function/5 +%%----------------------------------------------------------------- +emit_enum_read_function(_G, _N, _X, Fd, EnumName) -> + ic_codegen:emit(Fd, [" return ",EnumName,".from_int(_getIntFromName(_in.read_atom()));"]). + +%%----------------------------------------------------------------- +%% Func: emit_enum_write_function/5 +%%----------------------------------------------------------------- +emit_enum_write_function(_G, _N, _X, Fd, _EnumName) -> + ic_codegen:emit(Fd, " _out.write_atom(_members[_value.value()]);\n"). + + +%%----------------------------------------------------------------- +%% Func: enum_member_name_list/3 +%% +%% Note: The names generated are checked for name coalition +%% with java keywords. If so the name is always prefixed +%% by "_" +%%----------------------------------------------------------------- +enum_member_name_list(_G, _N, X) -> + lists:map( + fun(Enumerator) -> + ic_forms:get_java_id(Enumerator) + end, + ic_forms:get_body(X)). + +%%----------------------------------------------------------------- +%% Func: enum_member_atom_list/3 +%% +%% Note : Similar to the emit_member_list/3 but does not +%% solves name coalitions with java keywords. +%% Used for wire encoding only +%%----------------------------------------------------------------- +enum_member_atom_list(_G, _N, X) -> + lists:map( + fun(Enumerator) -> + ic_forms:get_id2(Enumerator) + end, + ic_forms:get_body(X)). + + + + + + + + |