Entries in symbol tables should always be added and removed using the methods provided by the symbol tables. Although it is possible to add and remove entries by directly manipulating the lists, that should never be done. The methods for adding and removing entries hide the underlying representation and using them will make it much easier to update your code if that representation changes. Even more importantly, most symbol table entries contain back pointers to the tables which hold them, and the adding and removing methods are responsible for maintaining those pointers and for performing a few other automatic checks and updates.
Types, symbols, and child symbol tables may be added using the
add_type
, add_sym
, and add_child
methods,
respectively. Each of these entries contains a pointer back to the
parent symbol table, and these methods automatically set those back
pointers. They do not, however, perform any other sanity checks, such
as checking for duplicate names. Similarly, the remove_type
,
remove_sym
, and remove_child
methods remove types,
symbols, and child symbol table entries. These methods clear the parent
pointers but do not delete the entries that are removed.
Variable definitions are treated a bit differently from other kinds of
symbol table entries. They do not have parent pointers so the
add_def
and remove_def
methods do not have to deal with
that. However, adding and removing variable definitions change some
attributes of the corresponding variables, and those attributes must be
automatically updated. First, each variable has a flag to indicate
whether a variable definition exists for it. A variable cannot have
more than one definition, so the add_def
method will fail if this
flag is already set. Otherwise, it sets the flag when the new
definition is added. Second, variable symbols also have a flag to
indicate whether they are actual definitions or just declarations of
symbols with external linkage. This extern
flag must be set to
FALSE
when a variable definition is added for a global variable.
When removing a variable definition, these flags must be reversed.
Unlike symbol nodes which always define separate symbols, multiple type
nodes can represent the same type. The basic add_type
method
will add a new type even if an equivalent type was already defined in
the same scope. In most cases, what is actually needed is a method to
first check if an equivalent type exists and if so to throw away the
duplicate and return the existing type. The install_type
method
provides this functionality. It first checks if a type has already been
entered in the symbol table or one of its ancestors using the
lookup_type
method. If so, it deletes the new type and returns
the existing one. If a type is not found, it is entered into the symbol
table and returned. All of the components of a type are recursively
installed before the type itself. This makes it easy to create new
types without worrying about duplicate entries in the symbol tables.