%%
%% %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
%%-----------------------------------------------------------------