From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- lib/ic/src/ic_symtab.erl | 232 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 lib/ic/src/ic_symtab.erl (limited to 'lib/ic/src/ic_symtab.erl') diff --git a/lib/ic/src/ic_symtab.erl b/lib/ic/src/ic_symtab.erl new file mode 100644 index 0000000000..889c75e3a2 --- /dev/null +++ b/lib/ic/src/ic_symtab.erl @@ -0,0 +1,232 @@ +%% +%% %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_symtab). + + +-include_lib("ic/src/ic.hrl"). +-include_lib("ic/src/icforms.hrl"). + +%%----------------------------------------------------------------- +%% External exports +%%----------------------------------------------------------------- +-export([new/0, store/3, retrieve/2, soft_retrieve/2, intf_resolv/3]). +-export([get_full_scoped_name/3, scoped_id_new_global/1, scoped_id_new/1]). +-export([scoped_id_strip/1,symtab_add_faked_included_types/1]). +-export([scoped_id_is_global/1, scoped_id_add/2]). + +%%----------------------------------------------------------------- +%% Internal exports +%%----------------------------------------------------------------- +-export([]). + +%%----------------------------------------------------------------- +%% External functions +%%----------------------------------------------------------------- + + +%%-------------------------------------------------------------------- +%% +%% Symbol table routines +%% +%% Symbol tables handles mappings Id -> Value, where Id is an +%% ordinary Id from the parser (or a string) and value is an +%% arbitrary term. +%% +%%-------------------------------------------------------------------- + +%%----------------------------------------------------------------- +%% Func: new/0 (used to be symtab_new) +%%----------------------------------------------------------------- +new() -> + ets:new(symtab, [set, public]). + +%%----------------------------------------------------------------- +%% Func: store/3 (used to be symtab_store) +%%----------------------------------------------------------------- +store(G, N, X) -> + Name = [ic_forms:get_id2(X) | N], + %%io:format("Adding id: ~p~n", [N]), + case soft_retrieve(G, Name) of + {error, _} -> + ets:insert(G#genobj.symtab, {Name, X}); + {ok, Y} when is_record(Y, forward) -> + ets:insert(G#genobj.symtab, {Name, X}); + {ok, _Y} -> + ic_error:error(G, {multiply_defined, X}) + end. + + +%%----------------------------------------------------------------- +%% Func: retrieve/2 (used to be symtab_retrieve) +%% +%% Makes a lookup in the symbol table for Id. Will throw +%% not_found if it fails. +%%----------------------------------------------------------------- +retrieve(G, Id) -> + case ets:lookup(G#genobj.symtab, Id) of + [{_, Val}] -> Val; + [] -> ic_error:error(G, {symtab_not_found, Id}) + end. + + +%%----------------------------------------------------------------- +%% Func: soft_retrieve/2 (used to be symtab_soft_retrieve) +%% +%% Same as retrieve but will use tagged return values. +%% +%%----------------------------------------------------------------- +soft_retrieve(G, Id) -> + case ets:lookup(G#genobj.symtab, Id) of + [{_, Val}] -> {ok, Val}; + [] -> {error, {symtab_not_found, Id}} + end. + + +%%----------------------------------------------------------------- +%% Func: intf_resolv/3 and resolv2/3 +%% (used to be symtab_intf_resolv and symtab_intf_resolv2) +%% +%% Tries to resolv the interface identifier reference. The id can +%% be either a scoped name or an standard identifier. The +%% function returns a global reference to the id. +%% +%% Will throw not_found if the id really cannot be found. Will +%% throw illegal_forward if any forward references are founf in +%% the inheritance list. +%% +%%----------------------------------------------------------------- +intf_resolv(G, Scope, Id) -> + case scoped_id_is_global(Id) of + true -> + retrieve(G, Id), + Id; + false -> + intf_resolv2(G, Scope, Id) + end. + +intf_resolv2(G, Scope, Id) -> + N = scoped_id_add(Scope, Id), + case soft_retrieve(G, scoped_id_strip(N)) of + {ok, F} when is_record(F, forward) -> + ic_error:error(G, {illegal_forward, Id}), []; + {ok, _Val} -> + scoped_id_mk_global(N); + _ -> + case scoped_id_is_top(Scope) of + false -> + intf_resolv2(G, scoped_id_up_one(Scope), Id); + true -> + ic_error:error(G, {symtab_not_found, Id}), [] + end + end. + + + +%%-------------------------------------------------------------------- +%% +%% Scoped id routines +%% +%% A scoped id is an id written as M::Id in IDL. Scoped ids are +%% implemented as lists of id in reverse order, so M1::F1 becomes +%% [F1, M1]. +%% +%%-------------------------------------------------------------------- + +get_full_scoped_name(G, N, S) when element(1, S) == scoped_id -> + ictype:scoped_lookup(G, ic_genobj:tktab(G), N, S). + +scoped_id_new_global(Id) -> + X=scoped_id_new(Id), X#scoped_id{type=global}. + +scoped_id_new(Id) -> + #scoped_id{line=ic_forms:get_line(Id), id=[ic_forms:get_id(Id)]}. + +%% Adds one more id to the list of ids +scoped_id_add(S1, S2) when is_record(S2, scoped_id) -> + S1#scoped_id{id=S2#scoped_id.id ++ S1#scoped_id.id, + line=S2#scoped_id.line}; +scoped_id_add(S, Id) -> + S#scoped_id{id=[ic_forms:get_id(Id) | S#scoped_id.id], line=ic_forms:get_line(Id)}. + + +scoped_id_mk_global(S) -> S#scoped_id{type=global}. + +scoped_id_is_global(S) when is_record(S, scoped_id), S#scoped_id.type==global -> + true; +scoped_id_is_global(_) -> false. + +%% Top level scope (i.e no more cd ..) +scoped_id_is_top(S) when S#scoped_id.id==[] -> true; +scoped_id_is_top(_) -> false. + + +scoped_id_up_one(S) -> S#scoped_id{id=tl(S#scoped_id.id)}. % cd .. in scope +%%scoped_id_get_def(S) -> hd(S#scoped_id.id). % Last added id +scoped_id_strip(S) -> S#scoped_id.id. % Strips all junk + + + + +% Add CORBA:: that as if they +% were defined in an included file. +% This is only supported in the case +% of Corba backend +symtab_add_faked_included_types(G) -> + case ic_options:get_opt(G, be) of + false -> + %% Add TypeCode as if it were defiend in included file + ets:insert(G#genobj.symtab, {["CORBA"], + {interface,{'',0,"TypeCode"}, + [], + [], + [], + {tk_objref, + "IDL:omg.org/CORBA/TypeCode:1.0", + "TypeCode"}}}); + erl_corba -> + %% Add TypeCode as if it were defiend in included file + ets:insert(G#genobj.symtab, {["CORBA"], + {interface,{'',0,"TypeCode"}, + [], + [], + [], + {tk_objref, + "IDL:omg.org/CORBA/TypeCode:1.0", + "TypeCode"}}}); + erl_template -> + %% Add TypeCode as if it were defiend in included file + ets:insert(G#genobj.symtab, {["CORBA"], + {interface,{'',0,"TypeCode"}, + [], + [], + [], + {tk_objref, + "IDL:omg.org/CORBA/TypeCode:1.0", + "TypeCode"}}}); + _ -> + ok + end. + + + +%%----------------------------------------------------------------- +%% Internal functions +%%----------------------------------------------------------------- -- cgit v1.2.3