aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ic/src/ic_code.erl
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/ic/src/ic_code.erl
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/ic/src/ic_code.erl')
-rw-r--r--lib/ic/src/ic_code.erl584
1 files changed, 584 insertions, 0 deletions
diff --git a/lib/ic/src/ic_code.erl b/lib/ic/src/ic_code.erl
new file mode 100644
index 0000000000..6802b9ca65
--- /dev/null
+++ b/lib/ic/src/ic_code.erl
@@ -0,0 +1,584 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-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_code).
+
+
+-include_lib("ic/src/ic.hrl").
+-include_lib("ic/src/icforms.hrl").
+
+%%-----------------------------------------------------------------
+%% External exports
+%%-----------------------------------------------------------------
+-export([get_basetype/2, insert_typedef/3, codeDirective/2]).
+-export([gen_includes/3, gen_includes/4, mk_list/1]).
+
+-export([type_expand_op/4, type_expand_handle_op/4]).
+-export([ type_expand_op_exec/4, type_expand_all/6, type_expand/7]).
+
+-export([type_expand_null/3, type_expand_void/3, type_expand_float/3, type_expand_double/3]).
+-export([type_expand_short/3, type_expand_ushort/3, type_expand_long/3, type_expand_ulong/3]).
+-export([type_expand_longlong/3, type_expand_ulonglong/3]).
+-export([type_expand_char/3, type_expand_wchar/3, type_expand_boolean/3]).
+-export([type_expand_octet/3, type_expand_any/3, type_expand_wstring/3]).
+-export([type_expand_object/3, type_expand_string/3, type_expand_struct/7, type_expand_union/7]).
+-export([type_expand_enum/4, type_expand_sequence/7, type_expand_array/7, type_expand_error/3]).
+
+-export([type_expand_struct_rule/3, type_expand_union_rule/2, type_expand_enum_rule/4]).
+-export([type_expand_enum_elements/3, type_expand_longdouble/3, type_expand_typecode/3]).
+-export([type_expand_principal/3, type_expand_exception/7]).
+
+%%-----------------------------------------------------------------
+%% External functions
+%%-----------------------------------------------------------------
+
+%%-------------------------------------------------------------------------------------
+%%
+%% Trackrecording of generated sequence type structs, thist is just used for C today.
+%%
+%%-------------------------------------------------------------------------------------
+
+get_basetype(G, MyId) ->
+ case ?lookup(ic_genobj:typedeftab(G), MyId) of
+ [] ->
+ MyId;
+ X ->
+ get_basetype(G, X)
+ end.
+
+insert_typedef(_G, "erlang_term", _) ->
+ ok;
+insert_typedef(G, MyId, DefinedAsId) ->
+ ?insert(ic_genobj:typedeftab(G), MyId, DefinedAsId).
+
+codeDirective(G,X) ->
+ case produceCode(X) of
+ true ->
+ case ic_options:get_opt(G, be) of
+ c_genserv ->
+ c;
+ c_client ->
+ c;
+ c_server ->
+ c_server;
+ _ ->
+ erlang
+ end;
+ false ->
+ case ic_options:get_opt(G, be) of
+ c_genserv ->
+ c_no_stub;
+ c_client ->
+ c_no_stub;
+ c_server ->
+ c_server_no_stub;
+ _ ->
+ erlang_no_stub
+ end
+ end.
+
+%% Checks if X should produce code
+produceCode(X) when is_record(X, module) ->
+ case ic_forms:get_body(X) of
+ [] ->
+ true;
+ List ->
+ produceModuleCode(List)
+ end;
+produceCode(_X) ->
+ false.
+
+produceModuleCode([]) ->
+ false;
+produceModuleCode([X|_Xs]) when is_record(X, const) ->
+ true;
+produceModuleCode([_X|Xs]) ->
+ produceModuleCode(Xs).
+
+%% Includes needed c file headers for included idl files
+gen_includes(Fd,G,Type) ->
+ case Type of
+ c_client ->
+ IncludeList =
+ ic_pragma:get_included_c_headers(G),
+ gen_includes_loop(Fd,IncludeList,Type);
+ c_server ->
+ IncludeList =
+ ic_pragma:get_included_c_headers(G),
+ gen_includes_loop(Fd,IncludeList,Type);
+ _ ->
+ ok
+ end,
+ ic_codegen:nl(Fd),
+ ic_codegen:emit(Fd, "#ifdef __cplusplus\n"),
+ ic_codegen:emit(Fd, "extern \"C\" {\n"),
+ ic_codegen:emit(Fd, "#endif\n\n").
+
+
+%% Includes needed c file headers for local interfaces
+gen_includes(Fd,G,X,Type) ->
+ case Type of
+ c_client ->
+ IncludeList =
+ ic_pragma:get_local_c_headers(G,X),
+ gen_includes_loop(Fd,IncludeList,Type);
+ c_server ->
+ IncludeList =
+ ic_pragma:get_local_c_headers(G,X),
+ gen_includes_loop(Fd,IncludeList,Type);
+ _ ->
+ ok
+ end,
+ ic_codegen:nl(Fd),
+ ic_codegen:emit(Fd, "#ifdef __cplusplus\n"),
+ ic_codegen:emit(Fd, "extern \"C\" {\n"),
+ ic_codegen:emit(Fd, "#endif\n\n").
+
+
+gen_includes_loop(_,[],_) ->
+ ok;
+gen_includes_loop(Fd,[I|Is],Type) ->
+ L = string:tokens(I,"/"),
+ File = lists:last(L),
+ case File of
+ "erlang" -> % Erlang is NOT generated that way !
+ gen_includes_loop(Fd,Is,Type);
+ "oe_erlang" -> % Erlang is NOT generated that way !
+ gen_includes_loop(Fd,Is,Type);
+ _ ->
+ case Type of
+ c_client ->
+ ic_codegen:emit(Fd, "#include \"~s.h\"\n", [File]);
+ c_server ->
+ ic_codegen:emit(Fd, "#include \"~s__s.h\"\n", [File])
+ end,
+ gen_includes_loop(Fd,Is,Type)
+ end.
+
+
+
+
+%%
+%% Used in NOC only
+%%
+
+
+%%
+%% Type expand on function head comments
+%%
+type_expand_op(G,N,X,Fd) ->
+ case catch type_expand_op_exec(G,N,X,Fd) of
+ {'EXIT',_Reason} ->
+ ic_codegen:nl(Fd),
+ ic_codegen:emit(Fd,"%% Error under type expansion, does not affect generated code.~n",[]),
+ ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[]);
+ _ ->
+ ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[])
+ end.
+
+
+type_expand_op_exec(G,N,X,Fd) ->
+ InArgs = ic:filter_params([in,inout], X#op.params),
+ OutArgs = ic:filter_params([out,inout], X#op.params),
+ ParamNr = length(InArgs)+1,
+ Tabs = "",
+
+ ic_codegen:nl(Fd),
+ ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[]),
+
+ case ic_forms:is_oneway(X) of
+ false ->
+ ic_codegen:emit(Fd,"%% Operation: ~s/~p~n",[ic_forms:get_id2(X),ParamNr]);
+ true ->
+ ic_codegen:emit(Fd,"%% Operation: ~s/~p (oneway)~n",[ic_forms:get_id2(X),ParamNr])
+ end,
+
+ if X#op.raises == [] -> [];
+ true ->
+ ic_codegen:emit(Fd,"%%~n",[]),
+ RaisesList=["%% Raises: " ++
+ mk_list(lists:map(fun(E) -> ic_util:to_colon(E) end,
+ X#op.raises))],
+ ic_codegen:emit(Fd,RaisesList,[]),
+ ic_codegen:nl(Fd)
+ end,
+
+ %% Print argument names
+ ic_codegen:emit(Fd,"%%\n",[]),
+ InArgNames = ["OE_Ref"]++[ic_util:mk_var(ic_forms:get_id(InArg#param.id)) || InArg <- InArgs ],
+ OutArgNames = ["Ret"]++[ic_util:mk_var(ic_forms:get_id(OutArg#param.id)) || OutArg <- OutArgs ],
+ case length(InArgNames) > 1 of
+ true ->
+ ic_codegen:emit(Fd,"%% Input value(s) : ~s~n",[mk_list(InArgNames)]);
+ false ->
+ ic_codegen:emit(Fd,"%% Input value : ~s~n",[mk_list(InArgNames)])
+ end,
+ case length(OutArgNames) > 1 of
+ true ->
+ ic_codegen:emit(Fd,"%% Return value(s) : ~s~n",[mk_list(OutArgNames)]);
+ false ->
+ ic_codegen:emit(Fd,"%% Return value : ~s~n",[mk_list(OutArgNames)])
+ end,
+ ic_codegen:emit(Fd,"%%\n",[]),
+
+ InArgsTypeList =
+ [{ic_util:mk_var(ic_forms:get_id(InArg#param.id)),ic_forms:get_tk(InArg)} || InArg <- InArgs ],
+ case InArgsTypeList of
+ [] -> %% no input parameters
+ ok;
+ _ ->
+ ic_codegen:emit(Fd,"%% --input-params-~n",[]),
+ type_expand_all(G,N,X,Fd,Tabs,InArgsTypeList)
+ end,
+
+ ReturnTypeList =[{"Ret",X#op.tk}],
+ ic_codegen:emit(Fd,"%% --return-value-~n",[]),
+ type_expand_all(G,N,X,Fd,Tabs,ReturnTypeList),
+
+ OutArgsTypeList =
+ [{ic_util:mk_var(ic_forms:get_id(OutArg#param.id)),ic_forms:get_tk(OutArg)} || OutArg <- OutArgs ],
+ case OutArgsTypeList of
+ [] -> %% no input parameters
+ ok;
+ _ ->
+ ic_codegen:emit(Fd,"%% -output-values-~n",[]),
+ type_expand_all(G,N,X,Fd,Tabs,OutArgsTypeList)
+ end.
+
+
+
+
+type_expand_handle_op(G,N,X,Fd) ->
+ case catch type_expand_handle_op_exec(G,N,X,Fd) of
+ {'EXIT',_Reason} ->
+ ic_codegen:nl(Fd),
+ ic_codegen:emit(Fd,"%% Error under type expansion, does not affect generated code.~n",[]),
+ ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[]);
+ _ ->
+ ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[])
+ end.
+
+
+type_expand_handle_op_exec(_G,_N,X,Fd) ->
+ InArgs = ic:filter_params([in,inout], X#op.params),
+ ParamNr = length(InArgs)+1,
+
+ ic_codegen:nl(Fd),
+ ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[]),
+
+ case ic_forms:is_oneway(X) of
+ false ->
+ ic_codegen:emit(Fd,"%% Handle operation: handle_call/3~n",[]);
+ true ->
+ ic_codegen:emit(Fd,"%% Handle operation: handle_cast/3~n",[])
+ end,
+ ic_codegen:emit(Fd,"%%~n",[]),
+ ic_codegen:emit(Fd,"%% Used for operation ~s/~p implementation~n",[ic_forms:get_id2(X),ParamNr]).
+
+
+
+type_expand_all(_G,_N,_X,_Fd,_Tabs,[]) ->
+ ok;
+type_expand_all(G,N,X,Fd,Tabs,[{ArgName,Type}|Rest]) ->
+ type_expand(G,N,X,Fd,Tabs,ArgName,Type),
+ type_expand_all(G,N,X,Fd,Tabs,Rest);
+type_expand_all(G,N,X,Fd,Tabs,[{default,_ArgName,Type}|Rest]) ->
+ type_expand(G,N,X,Fd,Tabs,"Def",Type),
+ type_expand_all(G,N,X,Fd,Tabs,Rest);
+type_expand_all(G,N,X,Fd,Tabs,[{LabelNr,_ArgName,Type}|Rest]) when is_integer(LabelNr) ->
+ type_expand(G,N,X,Fd,Tabs,"V" ++ integer_to_list(LabelNr),Type),
+ type_expand_all(G,N,X,Fd,Tabs,Rest);
+type_expand_all(G,N,X,Fd,Tabs,[{Label,_ArgName,Type}|Rest]) ->
+ type_expand(G,N,X,Fd,Tabs,Label,Type),
+ type_expand_all(G,N,X,Fd,Tabs,Rest).
+
+
+
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_null) ->
+ type_expand_null(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_void) ->
+ type_expand_void(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_float) ->
+ type_expand_float(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_double) ->
+ type_expand_double(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_longdouble) ->
+ type_expand_longdouble(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_short) ->
+ type_expand_short(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_ushort) ->
+ type_expand_ushort(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_long) ->
+ type_expand_long(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_longlong) ->
+ type_expand_longlong(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_ulong) ->
+ type_expand_ulong(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_ulonglong) ->
+ type_expand_ulonglong(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_char) ->
+ type_expand_char(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_wchar) ->
+ type_expand_wchar(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_boolean) ->
+ type_expand_boolean(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_octet) ->
+ type_expand_octet(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_any) ->
+ type_expand_any(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_TypeCode) ->
+ type_expand_typecode(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,tk_Principal) ->
+ type_expand_principal(Fd,Tabs,Name);
+type_expand(G, N, X,Fd,Tabs,Name, {tk_except, Id, ExcName, ElementList}) ->
+ type_expand_exception(G, N, X, Fd,Tabs,Name,
+ {tk_except, Id, ExcName, ElementList});
+type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_fixed, _Digits, _Scale}) ->
+ type_expand_fixed(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_objref, _IFRId, _ObjTabs, _ObjName}) ->
+ type_expand_object(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_objref, _IFRId, _ObjName}) ->
+ type_expand_object(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_string, _Length}) ->
+ type_expand_string(Fd,Tabs,Name);
+type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_wstring, _Length}) ->
+ type_expand_wstring(Fd,Tabs,Name);
+type_expand(G,N,X,Fd,Tabs,Name,{tk_union, IFRId, UnionName, DTC, DNr, LblList}) ->
+ type_expand_union(G,N,X,Fd,Tabs,Name,{tk_union, IFRId, UnionName, DTC, DNr, LblList});
+type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_enum, IFRId, EnumName, ElemNameList}) ->
+ type_expand_enum(Fd,Tabs,Name,{tk_enum, IFRId, EnumName, ElemNameList});
+type_expand(G,N,X,Fd,Tabs,Name,{tk_sequence, ElemTC, Length}) ->
+ type_expand_sequence(G,N,X,Fd,Tabs,Name,{tk_sequence, ElemTC, Length});
+type_expand(G,N,X,Fd,Tabs,Name,{tk_array, ElemTC, Length}) ->
+ type_expand_array(G,N,X,Fd,Tabs,Name,{tk_array, ElemTC, Length});
+type_expand(G,N,X,Fd,Tabs,Name,{tk_struct, IFRId, StructName, TcList}) ->
+ type_expand_struct(G,N,X,Fd,Tabs,Name,{tk_struct, IFRId, StructName, TcList});
+type_expand(_G,_N,_X,Fd,Tabs,Name,_) ->
+ type_expand_error(Fd,Tabs,Name).
+
+
+%% Basic OMG IDL types
+
+type_expand_null(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = null()~n",[Tabs,Name]).
+
+type_expand_void(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = void()~n",[Tabs,Name]).
+
+type_expand_float(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = float()~n",[Tabs,Name]).
+
+type_expand_double(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = double()~n",[Tabs,Name]).
+
+type_expand_longdouble(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = long_double()~n",[Tabs,Name]).
+
+type_expand_short(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = short()~n",[Tabs,Name]).
+
+type_expand_ushort(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = unsigned_Short()~n",[Tabs,Name]).
+
+type_expand_long(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = long()~n",[Tabs,Name]).
+
+type_expand_longlong(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = long_Long()~n",[Tabs,Name]).
+
+type_expand_ulong(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = unsigned_Long()~n",[Tabs,Name]).
+
+type_expand_ulonglong(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = unsigned_Long_Long()~n",[Tabs,Name]).
+
+type_expand_char(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = char()~n",[Tabs,Name]).
+
+type_expand_wchar(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = wchar()~n",[Tabs,Name]).
+
+type_expand_boolean(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = boolean()~n",[Tabs,Name]).
+
+type_expand_octet(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = octet()~n",[Tabs,Name]).
+
+type_expand_any(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = any()~n",[Tabs,Name]).
+
+type_expand_typecode(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = TypeCode()~n",[Tabs,Name]).
+
+type_expand_principal(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = principal()~n",[Tabs,Name]).
+
+
+type_expand_fixed(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = fixed()~n",[Tabs,Name]).
+
+type_expand_object(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = Object_Ref()~n",[Tabs,Name]).
+
+
+%% Constructed OMG IDL types
+
+type_expand_string(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = String()~n",[Tabs,Name]).
+
+type_expand_wstring(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = WString()~n",[Tabs,Name]).
+
+type_expand_exception(G, N, X, Fd, Tabs, Name, {tk_except, Id, ExcName, ElementList}) ->
+ ScopedStructName = getScopedName(G, N, ExcName, Id),
+ ic_codegen:emit(Fd,"%%~s ~s = ",[Tabs, Name]),
+ type_expand_exception_rule(Fd, ScopedStructName, ElementList),
+ type_expand_all(G, N, X, Fd, Tabs, ElementList).
+
+type_expand_struct(G,N,X,Fd,Tabs,Name,{tk_struct, IFRId, StructName, TcList}) ->
+ ScopedStructName = getScopedName(G,N,StructName,IFRId),
+ ic_codegen:emit(Fd,"%%~s ~s = ",[Tabs,Name]),
+ type_expand_struct_rule(Fd,ScopedStructName,TcList),
+ type_expand_all(G,N,X,Fd,Tabs,TcList).
+
+type_expand_union(G,N,X,Fd,Tabs,Name,{tk_union, IFRId, UnionName, DTC, _DNr, LblList}) ->
+ ScopedUnionName = getScopedName(G,N,UnionName,IFRId),
+ ic_codegen:emit(Fd,"%%~s ~s = #'~s'{label, value}\n",[Tabs,Name,ScopedUnionName]),
+ type_expand(G,N,X,Fd,Tabs,"label",DTC),
+ ic_codegen:emit(Fd,"%%~s value = ",[Tabs]),
+ type_expand_union_rule(Fd,LblList),
+ type_expand_all(G,N,X,Fd,Tabs,LblList).
+
+type_expand_enum(Fd,Tabs,Name,{tk_enum, _IFRId, EnumName, ElemNameList}) ->
+ ic_codegen:emit(Fd,"%%~s ~s = ~s~n",[Tabs,Name,EnumName]),
+ type_expand_enum_rule(Fd,Tabs,EnumName,ElemNameList).
+
+type_expand_sequence(G,N,X,Fd,Tabs,Name,{tk_sequence, ElemTC, _Length}) ->
+ ic_codegen:emit(Fd,"%%~s ~s = [ ~sElem ]~n",[Tabs,Name,Name]),
+ type_expand(G,N,X,Fd,Tabs,Name++"Elem",ElemTC).
+
+type_expand_array(G,N,X,Fd,Tabs,Name,{tk_array, ElemTC, _Length}) ->
+ ic_codegen:emit(Fd,"%%~s ~s = { ~sElem[,..~sElem] }~n",[Tabs,Name,Name,Name]),
+ type_expand(G,N,X,Fd,Tabs,Name++"Elem",ElemTC).
+
+type_expand_error(Fd,Tabs,Name) ->
+ ic_codegen:emit(Fd,"%%~s ~s = ????~n",[Tabs,Name]).
+
+
+type_expand_exception_rule(Fd,_Name,[]) ->
+ ic_codegen:emit(Fd," ???? ");
+type_expand_exception_rule(Fd,Name,TcList) ->
+ ic_codegen:emit(Fd,"#'~s'{",[Name]),
+ type_expand_exception_rule(Fd,TcList).
+
+type_expand_exception_rule(Fd,[{Name,_TC}]) ->
+ ic_codegen:emit(Fd,"~s}~n",[Name]);
+type_expand_exception_rule(Fd,[{Name,_TC}|Rest]) ->
+ ic_codegen:emit(Fd,"~s,",[Name]),
+ type_expand_exception_rule(Fd,Rest).
+
+type_expand_struct_rule(Fd,_Name,[]) ->
+ ic_codegen:emit(Fd," ???? ");
+type_expand_struct_rule(Fd,Name,TcList) ->
+ ic_codegen:emit(Fd,"#'~s'{",[Name]),
+ type_expand_struct_rule(Fd,TcList).
+
+type_expand_struct_rule(Fd,[{Name,_TC}]) ->
+ ic_codegen:emit(Fd,"~s}~n",[Name]);
+type_expand_struct_rule(Fd,[{Name,_TC}|Rest]) ->
+ ic_codegen:emit(Fd,"~s,",[Name]),
+ type_expand_struct_rule(Fd,Rest).
+
+
+type_expand_union_rule(Fd,[]) ->
+ ic_codegen:emit(Fd," ????");
+type_expand_union_rule(Fd,[{default,_Name,_TC}]) ->
+ ic_codegen:emit(Fd,"Def~n",[]);
+type_expand_union_rule(Fd,[{LNr,_Name,_TC}]) when is_integer(LNr)->
+ ic_codegen:emit(Fd,"V~p~n",[LNr]);
+type_expand_union_rule(Fd,[{Label,_Name,_TC}]) ->
+ ic_codegen:emit(Fd,"~s~n",[Label]);
+type_expand_union_rule(Fd,[{default,_Name,_TC}|Rest]) ->
+ ic_codegen:emit(Fd,"Default | "),
+ type_expand_union_rule(Fd,Rest);
+type_expand_union_rule(Fd,[{LNr,_Name,_TC}|Rest]) when is_integer(LNr) ->
+ ic_codegen:emit(Fd,"V~p | ",[LNr]),
+ type_expand_union_rule(Fd,Rest);
+type_expand_union_rule(Fd,[{Label,_Name,_TC}|Rest]) ->
+ ic_codegen:emit(Fd,"~s | ",[Label]),
+ type_expand_union_rule(Fd,Rest).
+
+
+type_expand_enum_rule(Fd,Tabs,Name,[]) ->
+ ic_codegen:emit(Fd,"%%~s ~s = ????",[Tabs,Name]);
+type_expand_enum_rule(Fd,Tabs,Name,ElList) ->
+ ic_codegen:emit(Fd,"%%~s ~s = ",[Tabs,Name]),
+ type_expand_enum_rule(Fd,ElList).
+
+type_expand_enum_rule(Fd,[ElName]) ->
+ ic_codegen:emit(Fd,"'~s' ~n",[ElName]);
+type_expand_enum_rule(Fd,[First|Rest]) ->
+ ic_codegen:emit(Fd,"'~s' | ",[First]),
+ type_expand_enum_rule(Fd,Rest).
+
+type_expand_enum_elements(_Fd,_Tabs,[]) ->
+ ok;
+type_expand_enum_elements(Fd,Tabs,[Elem|Elems]) ->
+ ic_codegen:emit(Fd,"%%~s ~s = Atom()~n",[Tabs,Elem]),
+ type_expand_enum_elements(Fd,Tabs,Elems).
+
+
+
+%% Returns the right scoped name to be used
+%% along with the expansion comments
+getScopedName(G,N,Name,IfrId) ->
+ PTab = ic_genobj:pragmatab(G),
+ case ets:match(PTab,{alias,'$0',IfrId}) of
+ [] -> %% No Alias - should never happen
+ ic_util:to_undersc(ic_pragma:mk_scope(IfrId));
+ [[[_S|N]]] -> %% An alias
+ ic_util:to_undersc([Name|N]);
+ [[[S|FoundScope]]] -> %% Maybe inherited
+ case ic_pragma:is_inherited_by(FoundScope,N,PTab) of
+ false -> %% Not inherited
+ ic_util:to_undersc([S|FoundScope]);
+ true -> %% inherited
+ ic_util:to_undersc([Name|N])
+ end
+ end.
+
+
+%% mk_list produces a nice comma separated
+%% string of variable names
+mk_list([]) -> [];
+mk_list([Arg | Args]) ->
+ Arg ++ mk_list2(Args).
+mk_list2([Arg | Args]) ->
+ ", " ++ Arg ++ mk_list2(Args);
+mk_list2([]) -> [].
+
+
+
+%%-----------------------------------------------------------------
+%% Internal functions
+%%-----------------------------------------------------------------
+
+
+