1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1998-2016. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20%% 21 22-module(ic_symtab). 23 24 25-include_lib("ic/src/ic.hrl"). 26-include_lib("ic/src/icforms.hrl"). 27 28%%----------------------------------------------------------------- 29%% External exports 30%%----------------------------------------------------------------- 31-export([new/0, store/3, retrieve/2, soft_retrieve/2, intf_resolv/3]). 32-export([get_full_scoped_name/3, scoped_id_new_global/1, scoped_id_new/1]). 33-export([scoped_id_strip/1,symtab_add_faked_included_types/1]). 34-export([scoped_id_is_global/1, scoped_id_add/2]). 35 36%%----------------------------------------------------------------- 37%% Internal exports 38%%----------------------------------------------------------------- 39-export([]). 40 41%%----------------------------------------------------------------- 42%% External functions 43%%----------------------------------------------------------------- 44 45 46%%-------------------------------------------------------------------- 47%% 48%% Symbol table routines 49%% 50%% Symbol tables handles mappings Id -> Value, where Id is an 51%% ordinary Id from the parser (or a string) and value is an 52%% arbitrary term. 53%% 54%%-------------------------------------------------------------------- 55 56%%----------------------------------------------------------------- 57%% Func: new/0 (used to be symtab_new) 58%%----------------------------------------------------------------- 59new() -> 60 ets:new(symtab, [set, public]). 61 62%%----------------------------------------------------------------- 63%% Func: store/3 (used to be symtab_store) 64%%----------------------------------------------------------------- 65store(G, N, X) -> 66 Name = [ic_forms:get_id2(X) | N], 67 %%io:format("Adding id: ~p~n", [N]), 68 case soft_retrieve(G, Name) of 69 {error, _} -> 70 ets:insert(G#genobj.symtab, {Name, X}); 71 {ok, Y} when is_record(Y, forward) -> 72 ets:insert(G#genobj.symtab, {Name, X}); 73 {ok, Y} when is_record(Y, constr_forward) -> 74 ets:insert(G#genobj.symtab, {Name, X}); 75 {ok, _Y} -> 76 ic_error:error(G, {multiply_defined, X}) 77 end. 78 79 80%%----------------------------------------------------------------- 81%% Func: retrieve/2 (used to be symtab_retrieve) 82%% 83%% Makes a lookup in the symbol table for Id. Will throw 84%% not_found if it fails. 85%%----------------------------------------------------------------- 86retrieve(G, Id) -> 87 case ets:lookup(G#genobj.symtab, Id) of 88 [{_, Val}] -> Val; 89 [] -> ic_error:error(G, {symtab_not_found, Id}) 90 end. 91 92 93%%----------------------------------------------------------------- 94%% Func: soft_retrieve/2 (used to be symtab_soft_retrieve) 95%% 96%% Same as retrieve but will use tagged return values. 97%% 98%%----------------------------------------------------------------- 99soft_retrieve(G, Id) -> 100 case ets:lookup(G#genobj.symtab, Id) of 101 [{_, Val}] -> {ok, Val}; 102 [] -> {error, {symtab_not_found, Id}} 103 end. 104 105 106%%----------------------------------------------------------------- 107%% Func: intf_resolv/3 and resolv2/3 108%% (used to be symtab_intf_resolv and symtab_intf_resolv2) 109%% 110%% Tries to resolv the interface identifier reference. The id can 111%% be either a scoped name or an standard identifier. The 112%% function returns a global reference to the id. 113%% 114%% Will throw not_found if the id really cannot be found. Will 115%% throw illegal_forward if any forward references are founf in 116%% the inheritance list. 117%% 118%%----------------------------------------------------------------- 119intf_resolv(G, Scope, Id) -> 120 case scoped_id_is_global(Id) of 121 true -> 122 retrieve(G, Id), 123 Id; 124 false -> 125 intf_resolv2(G, Scope, Id) 126 end. 127 128intf_resolv2(G, Scope, Id) -> 129 N = scoped_id_add(Scope, Id), 130 case soft_retrieve(G, scoped_id_strip(N)) of 131 {ok, F} when is_record(F, forward) -> 132 ic_error:error(G, {illegal_forward, Id}), []; 133 {ok, _Val} -> 134 scoped_id_mk_global(N); 135 _ -> 136 case scoped_id_is_top(Scope) of 137 false -> 138 intf_resolv2(G, scoped_id_up_one(Scope), Id); 139 true -> 140 ic_error:error(G, {symtab_not_found, Id}), [] 141 end 142 end. 143 144 145 146%%-------------------------------------------------------------------- 147%% 148%% Scoped id routines 149%% 150%% A scoped id is an id written as M::Id in IDL. Scoped ids are 151%% implemented as lists of id in reverse order, so M1::F1 becomes 152%% [F1, M1]. 153%% 154%%-------------------------------------------------------------------- 155 156get_full_scoped_name(G, N, S) when element(1, S) == scoped_id -> 157 ictype:scoped_lookup(G, ic_genobj:tktab(G), N, S). 158 159scoped_id_new_global(Id) -> 160 X=scoped_id_new(Id), X#scoped_id{type=global}. 161 162scoped_id_new(Id) -> 163 #scoped_id{line=ic_forms:get_line(Id), id=[ic_forms:get_id(Id)]}. 164 165%% Adds one more id to the list of ids 166scoped_id_add(S1, S2) when is_record(S2, scoped_id) -> 167 S1#scoped_id{id=S2#scoped_id.id ++ S1#scoped_id.id, 168 line=S2#scoped_id.line}; 169scoped_id_add(S, Id) -> 170 S#scoped_id{id=[ic_forms:get_id(Id) | S#scoped_id.id], line=ic_forms:get_line(Id)}. 171 172 173scoped_id_mk_global(S) -> S#scoped_id{type=global}. 174 175scoped_id_is_global(S) when is_record(S, scoped_id), S#scoped_id.type==global -> 176 true; 177scoped_id_is_global(_) -> false. 178 179%% Top level scope (i.e no more cd ..) 180scoped_id_is_top(S) when S#scoped_id.id==[] -> true; 181scoped_id_is_top(_) -> false. 182 183 184scoped_id_up_one(S) -> S#scoped_id{id=tl(S#scoped_id.id)}. % cd .. in scope 185%%scoped_id_get_def(S) -> hd(S#scoped_id.id). % Last added id 186scoped_id_strip(S) -> S#scoped_id.id. % Strips all junk 187 188 189 190 191% Add CORBA::<Types> that as if they 192% were defined in an included file. 193% This is only supported in the case 194% of Corba backend 195symtab_add_faked_included_types(G) -> 196 case ic_options:get_opt(G, be) of 197 false -> 198 %% Add TypeCode as if it were defiend in included file 199 ets:insert(G#genobj.symtab, {["CORBA"], 200 {interface,{'<identifier>',0,"TypeCode"}, 201 [], 202 [], 203 [], 204 {tk_objref, 205 "IDL:omg.org/CORBA/TypeCode:1.0", 206 "TypeCode"}}}); 207 erl_corba -> 208 %% Add TypeCode as if it were defiend in included file 209 ets:insert(G#genobj.symtab, {["CORBA"], 210 {interface,{'<identifier>',0,"TypeCode"}, 211 [], 212 [], 213 [], 214 {tk_objref, 215 "IDL:omg.org/CORBA/TypeCode:1.0", 216 "TypeCode"}}}); 217 erl_template -> 218 %% Add TypeCode as if it were defiend in included file 219 ets:insert(G#genobj.symtab, {["CORBA"], 220 {interface,{'<identifier>',0,"TypeCode"}, 221 [], 222 [], 223 [], 224 {tk_objref, 225 "IDL:omg.org/CORBA/TypeCode:1.0", 226 "TypeCode"}}}); 227 _ -> 228 ok 229 end. 230 231 232 233%%----------------------------------------------------------------- 234%% Internal functions 235%%----------------------------------------------------------------- 236