diff options
author | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
commit | 84adefa331c4159d432d22840663c38f155cd4c1 (patch) | |
tree | bff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/ic/src/ic_code.erl | |
download | otp-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.erl | 584 |
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 +%%----------------------------------------------------------------- + + + |