// $Id: symbol.h,v 1.11 1999/03/09 14:37:17 shields Exp $ copyright notice #ifndef symbol_INCLUDED #define symbol_INCLUDED #include "config.h" #include <assert.h> #include <stddef.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include "code.h" #include "stream.h" #include "option.h" #include "lookup.h" #include "depend.h" #include "access.h" #include "tuple.h" class Semantic; class SemanticEnvironment; class Ast; class AstCompilationUnit; class AstMethodDeclarator; class AstBlock; class AstList; class AstExpression; class AstVariableDeclarator; class ExpandedTypeTable; class ExpandedFieldTable; class ExpandedMethodTable; class SymbolTable; class SymbolSet; class Zip; class PackageSymbol; class PathSymbol : public Symbol { public: NameSymbol *name_symbol; Zip *zipfile; PathSymbol(NameSymbol *); virtual ~PathSymbol(); virtual wchar_t *Name() { return name_symbol -> Name(); } virtual int NameLength() { return name_symbol -> NameLength(); } virtual NameSymbol *Identity() { return name_symbol; } char *Utf8Name() { return (char *) (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL); } int Utf8NameLength() { return (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0); } inline bool IsZip() { return zipfile != NULL; } inline DirectorySymbol *RootDirectory() { return root_directory; } private: friend class SymbolTable; DirectorySymbol *root_directory; }; class DirectorySymbol : public Symbol { public: Symbol *owner; NameSymbol *name_symbol; Tuple<DirectorySymbol *> subdirectories; DirectorySymbol(NameSymbol *, Symbol *); virtual ~DirectorySymbol(); virtual wchar_t *Name() { return name_symbol -> Name(); } virtual int NameLength() { return name_symbol -> NameLength(); } virtual NameSymbol *Identity() { return name_symbol; } char *Utf8Name() { return (char *) (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL); } int Utf8NameLength() { return (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0); } DirectoryEntry *FindEntry(char *name, int len) { return (entries ? entries -> FindEntry(name, len) : (DirectoryEntry *) NULL); } #ifdef WIN32_FILE_SYSTEM DirectoryEntry *FindCaseInsensitiveEntry(char *name, int length) { return entries -> FindCaseInsensitiveEntry(name, length); } void InsertEntry(char *name, int length) { DirectoryEntry *entry = entries -> InsertEntry((DirectorySymbol *) this, name, length); entries -> InsertCaseInsensitiveEntry(entry); return; } #endif PathSymbol *PathSym() { return (owner -> PathCast() ? (PathSymbol *) owner : ((DirectorySymbol *) owner) -> PathSym()); } inline bool IsZip() { return PathSym() -> IsZip(); } void SetDirectoryName(); inline char *DirectoryName() { if (! directory_name) SetDirectoryName(); return directory_name; } inline int DirectoryNameLength() { if (! directory_name) SetDirectoryName(); return directory_name_length; } inline DirectorySymbol *InsertDirectorySymbol(NameSymbol *); inline DirectorySymbol *InsertAndReadDirectorySymbol(NameSymbol *); inline DirectorySymbol *FindDirectorySymbol(NameSymbol *); inline FileSymbol *InsertFileSymbol(NameSymbol *); inline FileSymbol *FindFileSymbol(NameSymbol *); void ResetDirectory(); private: time_t mtime; void ReadDirectory(); SymbolTable *table; inline SymbolTable *Table(); DirectoryTable *entries; char *directory_name; int directory_name_length; }; class FileSymbol : public Symbol { private: enum FileKind { JAVA, CLASS, CLASS_ONLY }; DirectorySymbol *output_directory; char *file_name; int file_name_length; public: NameSymbol *name_symbol; DirectorySymbol *directory_symbol; PackageSymbol *package; FileKind kind; // // These fields are used for files in zip packages. // u4 uncompressed_size; u4 date_time; long offset; // // This field holds the time of last data modification for a non-zip file // time_t mtime; LexStream *lex_stream; AstCompilationUnit *compilation_unit; Semantic *semantic; Tuple<TypeSymbol *> types; FileSymbol(NameSymbol *name_symbol_, NameSymbol *dirname_symbol = NULL) : name_symbol(name_symbol_), output_directory(NULL), directory_symbol(NULL), package(NULL), file_name(NULL), mtime(0), lex_stream(NULL), compilation_unit(NULL), semantic(NULL), types(4) { Symbol::_kind = _FILE; } virtual ~FileSymbol() { delete [] file_name; delete lex_stream; } FileSymbol *Clone() { FileSymbol *clone = new FileSymbol(name_symbol); clone -> kind = kind; clone -> directory_symbol = directory_symbol; clone -> mtime = mtime; return clone; } virtual wchar_t *Name() { return name_symbol -> Name(); } virtual int NameLength() { return name_symbol -> NameLength(); } virtual NameSymbol *Identity() { return name_symbol; } char *Utf8Name() { return (char *) (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL); } int Utf8NameLength() { return (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0); } inline void SetJava() { kind = JAVA; } inline void SetClass() { kind = CLASS; } inline void SetClassOnly() { kind = CLASS_ONLY; } inline bool IsJava() { return kind == JAVA; } inline bool IsClass() { return kind >= CLASS; } inline bool IsClassOnly() { return kind == CLASS_ONLY; } PathSymbol *PathSym() { return directory_symbol -> PathSym(); } inline bool IsZip() { return PathSym() -> IsZip(); } inline Zip *Zipfile() { return PathSym() -> zipfile; } static char *java_suffix; static int java_suffix_length; static char *class_suffix; static int class_suffix_length; static inline bool IsJavaSuffix(char *ptr); static inline bool IsClassSuffix(char *ptr); inline char *FileName() { if (! file_name) SetFileName(); return file_name; } inline int FileNameLength() { if (! file_name) SetFileName(); return file_name_length; } DirectorySymbol *OutputDirectory(); void SetFileName(); void CleanUp(); void Reset() { CleanUp(); delete [] file_name; file_name = NULL; types.Reset(); } }; class FileLocation { public: wchar_t *location; FileLocation (LexStream *lex_stream, LexStream::TokenIndex token_index) { char *file_name = lex_stream -> FileName(); int length = lex_stream -> FileNameLength(); location = new wchar_t[length + 13]; for (int i = 0; i < length; i++) { location[i] = (wchar_t) file_name[i]; } location[length++] = U_COLON; char str[13]; sprintf(str, "%i", lex_stream -> Line(token_index)); for (int j = 0; str[j]; j++) location[length++] = str[j]; location[length] = U_NULL; return; } FileLocation (FileSymbol *file_symbol) { char *file_name = file_symbol -> FileName(); int length = file_symbol -> FileNameLength(); location = new wchar_t[length + 13]; for (int i = 0; i < length; i++) { location[i] = (wchar_t) file_name[i]; } location[length] = U_NULL; return; } ~FileLocation() { delete [] location; } }; class PackageSymbol : public Symbol { public: Tuple<DirectorySymbol *> directory; PackageSymbol *owner; PackageSymbol(NameSymbol *name_symbol_, PackageSymbol *owner_) : name_symbol(name_symbol_), directory(4), owner(owner_), package_name(NULL), table(NULL) { Symbol::_kind = PACKAGE; } virtual ~PackageSymbol(); virtual wchar_t *Name() { return name_symbol -> Name(); } virtual int NameLength() { return name_symbol -> NameLength(); } virtual NameSymbol *Identity() { return name_symbol; } char *Utf8Name() { return (char *) (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL); } int Utf8NameLength() { return (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0); } void SetPackageName(); wchar_t *PackageName() { if (! package_name) SetPackageName(); return package_name; } int PackageNameLength() { if (! package_name) SetPackageName(); return package_name_length; } inline PackageSymbol *FindPackageSymbol(NameSymbol *); inline PackageSymbol *InsertPackageSymbol(NameSymbol *); inline TypeSymbol *FindTypeSymbol(NameSymbol *); inline TypeSymbol *InsertSystemTypeSymbol(NameSymbol *); inline TypeSymbol *InsertOuterTypeSymbol(NameSymbol *); inline void DeleteTypeSymbol(TypeSymbol *); private: NameSymbol *name_symbol; SymbolTable *table; inline SymbolTable *Table(); wchar_t *package_name; int package_name_length; }; class MethodSymbol : public Symbol, public AccessFlags { public: Ast *method_or_constructor_declaration; // AstMethodDeclaration or AstConstructorDeclaration NameSymbol *name_symbol; TypeSymbol *containing_type; BlockSymbol *block_symbol; MethodSymbol *next_method; Utf8LiteralValue *signature; // // If this method is a method that is generated in order to process initializer // blocks contained in the body of a class, it needs to know the set of // constructors that might invoke it in order to figure out which exceptions // can be safely thrown within an initializer block. // int NumInitializerConstructors() { return (initializer_constructors ? initializer_constructors -> Length() : 0); } MethodSymbol *InitializerConstructor(int i) { return (*initializer_constructors)[i]; } void AddInitializerConstructor(MethodSymbol *method) { if (! initializer_constructors) initializer_constructors = new Tuple<MethodSymbol *>(8); initializer_constructors -> Next() = method; } int max_block_depth, constant_pool_index, constant_pool_class; // // If the method in question is a private member, we may need to construct // another method that allows it to be accessed by inner classes. // MethodSymbol *read_method; // // If this method is a method that permits access to a private member of an // enclosing type then accessed_member identifies the member in question. // Symbol *accessed_member; virtual wchar_t *Name() { return name_symbol -> Name(); } virtual int NameLength() { return name_symbol -> NameLength(); } virtual NameSymbol *Identity() { return name_symbol; } char *Utf8Name() { return (char *) (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL); } int Utf8NameLength() { return (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0); } MethodSymbol(NameSymbol *name_symbol_) : method_or_constructor_declaration(NULL), name_symbol(name_symbol_), external_name_symbol(NULL), containing_type(NULL), block_symbol(NULL), next_method(NULL), signature(NULL), type_(NULL), status(0), header(NULL), max_block_depth(1), // there must be at least one block in a method // this default is useful for default constructors. constant_pool_index(0), constant_pool_class(0), local_constructor(NULL), read_method(NULL), accessed_member(NULL), formal_parameters(NULL), throws(NULL), throws_signatures(NULL), initializer_constructors(NULL) { Symbol::_kind = METHOD; } virtual ~MethodSymbol(); bool IsFinal(); bool IsTyped() { return type_ != NULL; } void SetType(TypeSymbol *_type) { type_ = _type; } void ProcessMethodSignature(Semantic *, LexStream::TokenIndex); void ProcessMethodThrows(Semantic *, LexStream::TokenIndex); TypeSymbol *Type(Semantic *sem = NULL, LexStream::TokenIndex tok = 0) { if (! type_) ProcessMethodSignature(sem, tok); assert(type_); return type_; } int NumFormalParameters(Semantic *sem = NULL, LexStream::TokenIndex tok = 0) { if (! type_) ProcessMethodSignature(sem, tok); assert(type_); return (formal_parameters ? formal_parameters -> Length() : 0); } VariableSymbol *FormalParameter(int i) { return (*formal_parameters)[i]; } void AddFormalParameter(VariableSymbol *variable) { if (! formal_parameters) formal_parameters = new Tuple<VariableSymbol *>(8); formal_parameters -> Next() = variable; } int NumThrows(Semantic *sem = NULL, LexStream::TokenIndex tok = 0) { if (throws_signatures) ProcessMethodThrows(sem, tok); assert(! throws_signatures); return (throws ? throws -> Length() : 0); } TypeSymbol *Throws(int i) { return (*throws)[i]; } void AddThrows(TypeSymbol *exception) { if (! throws) throws = new Tuple<TypeSymbol *>(8); throws -> Next() = exception; } int NumThrowsSignatures() { return (throws_signatures ? throws_signatures -> Length() : 0); } char *ThrowsSignature(int i) { return (*throws_signatures)[i]; } void AddThrowsSignature(char *signature_, int length) { char *signature = new char[length + 1]; strncpy(signature, signature_, length); signature[length] = U_NULL; if (! throws_signatures) throws_signatures = new Tuple<char *>(8); throws_signatures -> Next() = signature; } void SetGeneratedLocalConstructor(MethodSymbol *base_method) { assert(! base_method -> local_constructor); base_method -> local_constructor = this; this -> local_constructor = base_method; } bool IsGeneratedLocalConstructor() { return ((local_constructor != NULL) && (this -> external_name_symbol == NULL)); } MethodSymbol *LocalConstructor() { return local_constructor; } void SetExternalIdentity(NameSymbol *external_name_symbol_) { external_name_symbol = external_name_symbol_; } NameSymbol *ExternalIdentity() { return (external_name_symbol ? external_name_symbol : name_symbol); } wchar_t *ExternalName() { return (external_name_symbol ? external_name_symbol -> Name() : name_symbol -> Name()); } int ExternalNameLength() { return (external_name_symbol ? external_name_symbol -> NameLength() : name_symbol -> NameLength()); } char *ExternalUtf8Name() { return (char *) (external_name_symbol ? external_name_symbol -> Utf8_literal -> value : (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL)); } int ExternalUtf8NameLength() { return (external_name_symbol ? (external_name_symbol -> Utf8_literal ? external_name_symbol -> Utf8_literal -> length : 0) : (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0)); } void SetFlags(AccessFlags variable_access) { access_flags = variable_access.access_flags; } void SetContainingType(TypeSymbol *containing_type_) { containing_type = containing_type_; } void SetBlockSymbol(BlockSymbol *block_symbol_) { block_symbol = block_symbol_; } void SetSignature(Control &, VariableSymbol * = NULL); void SetSignature(Utf8LiteralValue *signature_) { signature = signature_; } char *SignatureString() { return signature -> value; } wchar_t *Header(Semantic * = NULL, LexStream::TokenIndex = 0); void CleanUp(); void MarkSynthetic() { status |= (unsigned char) 0x08; } bool IsSynthetic() { return status & (unsigned char) 0x08; } private: NameSymbol *external_name_symbol; unsigned char status; wchar_t *header; TypeSymbol *type_; Tuple<VariableSymbol *> *formal_parameters; Tuple<TypeSymbol *> *throws; Tuple<char *> *throws_signatures; Tuple<MethodSymbol *> *initializer_constructors; // // If the method in question is a constructor of a local type, we may need to construct // another constructor that accepts extra local parameters. // MethodSymbol *local_constructor; bool ACC_FINAL() { assert(! "use the ACC_FINAL() flag on a method symbol. Use the function IsFinal() instead"); return false; } }; class TypeSymbol : public Symbol, public AccessFlags { public: SemanticEnvironment *semantic_environment; Ast *declaration; // AstClassDeclaration or AstInterfaceDeclaration FileSymbol *file_symbol; FileLocation *file_location; NameSymbol *name_symbol; Symbol *owner; TypeSymbol *outermost_type; // An nested class identifies the outer most type that contains it. // If a class is not nested then it identifies itself as its outer // most type. TypeSymbol *super; TypeSymbol *base_type; // indicates the base type (type of elements in the last dimension) of an array // For a normal type base_type is NULL. If base_type is a "bad" type it points // to itsself (this). int index, // The first two variables is used in TypeCycleChecker to determine if this class or interface // forms a cycle in its "extends" or "implements" relationship. incremental_index; // This variable is used in TypeCycleChecker to determine which types (files) // need to be recompiled based on the "dependent" relationship. int NumLocalConstructorCallEnvironments() { return (local_constructor_call_environments ? local_constructor_call_environments -> Length() : 0); } SemanticEnvironment *&LocalConstructorCallEnvironment(int i) { return (*local_constructor_call_environments)[i]; } void AddLocalConstructorCallEnvironment(SemanticEnvironment *environment) { if (! local_constructor_call_environments) local_constructor_call_environments = new Tuple<SemanticEnvironment *>(8); local_constructor_call_environments -> Next() = environment; } int NumPrivateAccessMethods() { return (private_access_methods ? private_access_methods -> Length() : 0); } MethodSymbol *&PrivateAccessMethod(int i) { return (*private_access_methods)[i]; } void AddPrivateAccessMethod(MethodSymbol *method_symbol) { if (! private_access_methods) private_access_methods = new Tuple<MethodSymbol *>(8); private_access_methods -> Next() = method_symbol; } int NumPrivateAccessConstructors() { return (private_access_constructors ? private_access_constructors -> Length() : 0); } MethodSymbol *&PrivateAccessConstructor(int i) { return (*private_access_constructors)[i]; } void AddPrivateAccessConstructor(MethodSymbol *constructor_symbol) { if (! private_access_constructors) private_access_constructors = new Tuple<MethodSymbol *>(8); private_access_constructors -> Next() = constructor_symbol; } int NumConstructorParameters() { return (constructor_parameters ? constructor_parameters -> Length() : 0); } VariableSymbol *&ConstructorParameter(int i) { return (*constructor_parameters)[i]; } void AddConstructorParameter(VariableSymbol *variable_symbol) { if (! constructor_parameters) constructor_parameters = new Tuple<VariableSymbol *>(8); constructor_parameters -> Next() = variable_symbol; } int NumGeneratedConstructors() { return (generated_constructors ? generated_constructors -> Length() : 0); } MethodSymbol *&GeneratedConstructor(int i) { return (*generated_constructors)[i]; } void AddGeneratedConstructor(MethodSymbol *constructor_symbol) { if (! generated_constructors) generated_constructors = new Tuple<MethodSymbol *>(8); generated_constructors -> Next() = constructor_symbol; } int NumEnclosingInstances() { return (enclosing_instances ? enclosing_instances -> Length() : 0); } VariableSymbol *&EnclosingInstance(int i) { return (*enclosing_instances)[i]; } void AddEnclosingInstance(VariableSymbol *instance_symbol) { if (! enclosing_instances) enclosing_instances = new Tuple<VariableSymbol *>(8); enclosing_instances -> Next() = instance_symbol; } int NumClassLiterals() { return (class_literals ? class_literals -> Length() : 0); } VariableSymbol *&ClassLiteral(int i) { return (*class_literals)[i]; } void AddClassLiteral(VariableSymbol *literal_symbol) { if (! class_literals) class_literals = new Tuple<VariableSymbol *>(8); class_literals -> Next() = literal_symbol; } int NumNestedTypes() { return (nested_types ? nested_types -> Length() : 0); } TypeSymbol *&NestedType(int i) { return (*nested_types)[i]; } void AddNestedType(TypeSymbol *type_symbol) { if (! nested_types) nested_types = new Tuple<TypeSymbol *>(8); nested_types -> Next() = type_symbol; } int NumInterfaces() { return (interfaces ? interfaces -> Length() : 0); } void ResetInterfaces() { delete interfaces; interfaces = NULL; } TypeSymbol *Interface(int i) { return (*interfaces)[i]; } void AddInterface(TypeSymbol *type_symbol) { if (! interfaces) interfaces = new Tuple<TypeSymbol *>(8); interfaces -> Next() = type_symbol; } int num_anonymous_types() { return (anonymous_types ? anonymous_types -> Length() : 0); } TypeSymbol *&AnonymousType(int i) { return (*anonymous_types)[i]; } void AddAnonymousType(TypeSymbol *type_symbol) { if (! anonymous_types) anonymous_types = new Tuple<TypeSymbol *>(8); anonymous_types -> Next() = type_symbol; } void DeleteAnonymousTypes(); SymbolSet *local, *non_local; SymbolSet *supertypes_closure, *subtypes, *subtypes_closure, *innertypes_closure; SymbolSet *dependents, *parents, *dependents_closure, // processed in cycle.cpp *parents_closure; // processed in cycle.cpp int pool_index; // index of element in symbol_pool (in the relevant symbol table) that points to this type Utf8LiteralValue *signature; Utf8LiteralValue *fully_qualified_name; ExpandedTypeTable *expanded_type_table; ExpandedFieldTable *expanded_field_table; ExpandedMethodTable *expanded_method_table; int num_dimensions; MethodSymbol *static_initializer_method; MethodSymbol *block_initializer_method; virtual wchar_t *Name() { return name_symbol -> Name(); } virtual int NameLength() { return name_symbol -> NameLength(); } virtual NameSymbol *Identity() { return name_symbol; } char *Utf8Name() { return (char *) (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL); } int Utf8NameLength() { return (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0); } void SetExternalIdentity(NameSymbol *external_name_symbol_) { external_name_symbol = external_name_symbol_; } NameSymbol *ExternalIdentity() { return (external_name_symbol ? external_name_symbol : name_symbol); } wchar_t *ExternalName() { return (external_name_symbol ? external_name_symbol -> Name() : name_symbol -> Name()); } int ExternalNameLength() { return (external_name_symbol ? external_name_symbol -> NameLength() : name_symbol -> NameLength()); } char *ExternalUtf8Name() { return (char *) (external_name_symbol ? external_name_symbol -> Utf8_literal -> value : (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL)); } int ExternalUtf8NameLength() { return (external_name_symbol ? (external_name_symbol -> Utf8_literal ? external_name_symbol -> Utf8_literal -> length : 0) : (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0)); } TypeSymbol(NameSymbol *); virtual ~TypeSymbol(); void ProcessTypeHeaders(); void ProcessMembers(); void CompleteSymbolTable(); void ProcessExecutableBodies(); void RemoveCompilationReferences(); NameSymbol *GetThisName(Control &, int); VariableSymbol *FindThis(int k) { assert(IsInner()); assert(NumConstructorParameters() > 0); return (k == 0 ? ConstructorParameter(0) : (VariableSymbol *) (NumEnclosingInstances() > k ? EnclosingInstance(k) : NULL)); } VariableSymbol *InsertThis(int k); TypeSymbol *FindOrInsertClassLiteralClass(LexStream::TokenIndex); TypeSymbol *ClassLiteralClass() { return class_literal_class; } MethodSymbol *FindOrInsertClassLiteralMethod(Control &); MethodSymbol *ClassLiteralMethod() { return class_literal_method; } Utf8LiteralValue *FindOrInsertClassLiteralName(Control &); Utf8LiteralValue *ClassLiteralName() { return class_literal_name; } VariableSymbol *FindOrInsertClassLiteral(TypeSymbol *); VariableSymbol *FindOrInsertLocalShadow(VariableSymbol *); static MethodSymbol *GetReadAccessMethod(MethodSymbol *); static MethodSymbol *GetReadAccessMethod(VariableSymbol *); static MethodSymbol *GetWriteAccessMethod(VariableSymbol *); bool IsArray() { return (num_dimensions > 0); } void SetOwner(Symbol *owner_) { owner = owner_; } bool IsOwner(TypeSymbol *type) { Symbol *sym = type -> owner; while (! sym -> PackageCast()) { if (sym == this) return true; MethodSymbol *method = sym -> MethodCast(); sym = (method ? method -> containing_type : ((TypeSymbol *) sym) -> owner); } return false; } TypeSymbol *ContainingType() { if (owner) { TypeSymbol *type = owner -> TypeCast(); if (type) return type; MethodSymbol *method = owner -> MethodCast(); if (method) return method -> containing_type; } return NULL; } bool CanAccess(TypeSymbol *); bool HasProtectedAccessTo(TypeSymbol *); bool IsSubclass(TypeSymbol *super_class) { return (this == super_class ? true : (super == NULL ? false : super -> IsSubclass(super_class))); } bool IsSubinterface(TypeSymbol *super_interface) { if (this == super_interface) return true; for (int i = 0; i < NumInterfaces(); i++) { if (Interface(i) -> IsSubinterface(super_interface)) return true; } return false; } bool Implements(TypeSymbol *inter) { for (int i = 0; i < NumInterfaces(); i++) { if (Interface(i) -> IsSubinterface(inter)) return true; } return (this -> super ? this -> super -> Implements(inter) : false); } wchar_t *FileLoc() { return (wchar_t *) (file_location ? file_location -> location : NULL); } void SetLocation(); TypeSymbol *GetArrayType(Semantic *, int); TypeSymbol *ArraySubtype() { return this -> base_type -> Array(this -> num_dimensions - 1); } void SetSignature(Control &); void SetSignature(Utf8LiteralValue *signature_) { signature = signature_; } char *SignatureString() { return signature -> value; } void SetClassLiteralName(Utf8LiteralValue *class_literal_name_) { class_literal_name = class_literal_name_; } PackageSymbol *ContainingPackage() { return outermost_type -> owner -> PackageCast(); } void SetFlags(AccessFlags variable_access) { access_flags = variable_access.access_flags; } bool IsNestedIn(TypeSymbol *); bool IsNested() { return outermost_type != this; } bool IsTopLevel() { return (! IsNested()) || this -> ACC_STATIC(); } bool IsInner() { return (! IsTopLevel()); } bool IsLocal() { for (Symbol *sym = owner; ! sym -> PackageCast(); sym = ((TypeSymbol *) sym) -> owner) { if (sym -> MethodCast()) return true; } return false; } inline char *ClassName() { if (! class_name) SetClassName(); return class_name; } void MarkConstructorMembersProcessed() { status |= (unsigned short) 0x0001; } bool ConstructorMembersProcessed() { return status & (unsigned short) 0x0001; } void MarkMethodMembersProcessed() { status |= (unsigned short) 0x0002; } bool MethodMembersProcessed() { return status & (unsigned short) 0x0002; } void MarkFieldMembersProcessed() { status |= (unsigned short) 0x0004; } bool FieldMembersProcessed() { return status & (unsigned short) 0x0004; } void MarkLocalClassProcessingCompleted() { status |= (unsigned short) 0x0008; } bool LocalClassProcessingCompleted() { return status & (unsigned short) 0x0008; } void MarkSourcePending() { status |= (unsigned short) 0x0010; } void MarkSourceNoLongerPending() { status &= (~ ((unsigned short) 0x0010)); } bool SourcePending() { return status & (unsigned short) 0x0010; } void MarkAnonymous() { status |= (unsigned short) 0x0020; } bool Anonymous() { return status & (unsigned short) 0x0020; } void MarkHeaderProcessed() { status |= (unsigned short) 0x0040; } bool HeaderProcessed() { return status & (unsigned short) 0x0040; } void MarkPrimitive() { status |= (unsigned short) 0x0080; } bool Primitive() { return status & (unsigned short) 0x0080; } void MarkBad() { SetACC_PUBLIC(); status |= (unsigned short) 0x0100; MarkHeaderProcessed(); MarkConstructorMembersProcessed(); MarkMethodMembersProcessed(); MarkFieldMembersProcessed(); MarkLocalClassProcessingCompleted(); MarkSourceNoLongerPending(); return; } bool Bad() { return status & (unsigned short) 0x0100; } void MarkCircular() { status |= (unsigned short) 0x0200; MarkBad(); return; } void MarkNonCircular() { status &= (~ ((unsigned short) 0x0200)); } bool Circular() { return status & (unsigned short) 0x0200; } void ProcessNestedTypeSignatures(Semantic *, LexStream::TokenIndex); bool NestedTypesProcessed() { return nested_type_signatures == NULL; } int NumNestedTypeSignatures() { return (nested_type_signatures ? nested_type_signatures -> Length() : 0); } char *NestedTypeSignature(int i) { return (*nested_type_signatures)[i]; } void AddNestedTypeSignature(char *signature_, int length) { char *signature = new char[length + 1]; strncpy(signature, signature_, length); signature[length] = U_NULL; if (! nested_type_signatures) nested_type_signatures = new Tuple<char *>(8); nested_type_signatures -> Next() = signature; } inline void SetSymbolTable(int); inline SymbolTable *Table(); int NumVariableSymbols(); VariableSymbol *VariableSym(int); int NumMethodSymbols(); MethodSymbol *MethodSym(int); int NumTypeSymbols(); TypeSymbol *TypeSym(int); inline TypeSymbol *InsertAnonymousTypeSymbol(NameSymbol *); inline TypeSymbol *FindTypeSymbol(NameSymbol *); inline TypeSymbol *InsertNestedTypeSymbol(NameSymbol *); inline MethodSymbol *FindConstructorSymbol(); inline MethodSymbol *InsertConstructorSymbol(NameSymbol *); inline void InsertConstructorSymbol(MethodSymbol *); inline MethodSymbol *FindMethodSymbol(NameSymbol *); inline VariableSymbol *FindVariableSymbol(NameSymbol *); inline VariableSymbol *InsertVariableSymbol(NameSymbol *); inline void InsertVariableSymbol(VariableSymbol *); inline MethodSymbol *InsertMethodSymbol(NameSymbol *); inline void InsertMethodSymbol(MethodSymbol *); inline MethodSymbol *Overload(MethodSymbol *); inline void Overload(MethodSymbol *, MethodSymbol *); inline MethodSymbol *LocalConstructorOverload(MethodSymbol *); MethodSymbol *FindOverloadMethod(MethodSymbol *, AstMethodDeclarator *); inline void CompressSpace(); private: NameSymbol *external_name_symbol; SymbolTable *table; unsigned short status; PackageSymbol *package; char *class_name; void SetClassName(); TypeSymbol *class_literal_class; MethodSymbol *class_literal_method; Utf8LiteralValue *class_literal_name; // // For a local type, when we first encounter an embedded call // to one of its constructors or a constructor of one of its inner // types, either via a ClassInstanceCreation or an ExplicitConstructorInvocation, // we record it and resolve it after we have computed all necessary // information about the type and its inner types. // Tuple<SemanticEnvironment *> *local_constructor_call_environments; // // When an inner class tries to access a private member of one of its enclosing // classes, one (or two) access method(s) to read (and/or write) the private member // is (are) generated. // Tuple<MethodSymbol *> *private_access_methods; Tuple<MethodSymbol *> *private_access_constructors; // // For an accessible inner class the first elememt in this array // identifies the "this$0" pointer of the containing type. For a local // class, in addition to the this$0 pointer (if it is needed), all local // variables that are referred to in the local type are passed as argument // to the local type and copied in the constructor into a local field. These // local variables are stored in constructor_parameters. // // The array enclosing_instances is there for optimization purposes. // If this type is deeply nested within several other types and it makes // references to members in the enclosing types, then it might // be useful to keep a reference to each of these enclosing // instances in the form of this$0, this$1, this$2, ... // // The array class_identities is used to store static variables of type Class // that contain the proper value for a given type. // Tuple<VariableSymbol *> *constructor_parameters; Tuple<MethodSymbol *> *generated_constructors; Tuple<VariableSymbol *> *enclosing_instances; Tuple<VariableSymbol *> *class_literals; Tuple<char *> *nested_type_signatures; // // The inner types that appear immediately within this type in the order // in which they should be processed (compiled). Tuple<TypeSymbol *> *nested_types; // // The interfaces that were declared in the header of the type. // Tuple<TypeSymbol *> *interfaces; // // The anonymous types that were declared in this type. // Tuple<TypeSymbol *> *anonymous_types; // // The arrays of this type that were declared. // Tuple<TypeSymbol *> *array; inline int NumArrays() { return (array ? array -> Length() : 0); } inline TypeSymbol *Array(int i) { return (*array)[i]; } inline void AddArrayType(TypeSymbol *type_symbol) { if (! array) array = new Tuple<TypeSymbol *>(4); array -> Next() = type_symbol; } }; class VariableSymbol : public Symbol, public AccessFlags { public: Ast *declarator; NameSymbol *name_symbol; Symbol *owner; LiteralValue *initial_value; int constant_pool_index, constant_pool_class, local_program_counter; VariableSymbol *accessed_local; MethodSymbol *read_method, *write_method; virtual wchar_t *Name() { return name_symbol -> Name(); } virtual int NameLength() { return name_symbol -> NameLength(); } virtual NameSymbol *Identity() { return name_symbol; } char *Utf8Name() { return (char *) (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL); } int Utf8NameLength() { return (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0); } void SetExternalIdentity(NameSymbol *external_name_symbol_) { external_name_symbol = external_name_symbol_; } NameSymbol *ExternalIdentity() { return (external_name_symbol ? external_name_symbol : name_symbol); } wchar_t *ExternalName() { return (external_name_symbol ? external_name_symbol -> Name() : name_symbol -> Name()); } int ExternalNameLength() { return (external_name_symbol ? external_name_symbol -> NameLength() : name_symbol -> NameLength()); } char *ExternalUtf8Name() { return (char *) (external_name_symbol ? external_name_symbol -> Utf8_literal -> value : (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL)); } int ExternalUtf8NameLength() { return (external_name_symbol ? (external_name_symbol -> Utf8_literal ? external_name_symbol -> Utf8_literal -> length : 0) : (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0)); } VariableSymbol(NameSymbol *name_symbol_) : declarator(NULL), name_symbol(name_symbol_), external_name_symbol(NULL), owner(NULL), type_(NULL), signature_string(NULL), initial_value(NULL), local_variable_index_(-1), constant_pool_index(0), constant_pool_class(0), local_program_counter(0), accessed_local(NULL), read_method(NULL), write_method(NULL), status(0) { Symbol::_kind = VARIABLE; } virtual ~VariableSymbol() { delete [] signature_string; } void SetFlags(AccessFlags variable_access) { access_flags = variable_access.access_flags; } void SetOwner(Symbol *owner_) { owner = owner_; } void SetLocalVariableIndex(int index) { local_variable_index_ = index; MarkComplete(); } int LocalVariableIndex() { return local_variable_index_; } bool IsTyped() { return type_ != NULL; } void SetType(TypeSymbol *_type) { type_ = _type; } void ProcessVariableSignature(Semantic *, LexStream::TokenIndex); TypeSymbol *Type(Semantic *sem = NULL, LexStream::TokenIndex tok = 0) { if (! type_) ProcessVariableSignature(sem, tok); assert(type_); return type_; } void SetSignatureString(char *signature_, int length) { signature_string = new char[length + 1]; strncpy(signature_string, signature_, length); signature_string[length] = U_NULL; } bool IsLocal() { return owner -> MethodCast() != NULL; } // is variable a local variable? bool IsLocal(MethodSymbol *method) { return owner == method; } // is variable local to a particular method ? bool IsFinal(TypeSymbol *type) { return (owner == type && ACC_FINAL()); } // // These functions are used to identify when the declaration of a field in the body of a class is // complete. // void MarkIncomplete() { status &= (~((unsigned char) 0x01)); } void MarkComplete() { status |= (unsigned char) 0x01; } bool IsDeclarationComplete() { return status & (unsigned char) 0x01; } void MarkNotDefinitelyAssigned() { status &= (~((unsigned char) 0x02)); } void MarkDefinitelyAssigned() { status |= (unsigned char) 0x02; } bool IsDefinitelyAssigned() { return status & (unsigned char) 0x02; } void MarkPossiblyAssigned() { status |= (unsigned char) 0x04; } bool IsPossiblyAssigned() { return status & (unsigned char) 0x04; } void MarkSynthetic() { status |= (unsigned char) 0x08; } bool IsSynthetic() { return status & (unsigned char) 0x08; } private: NameSymbol *external_name_symbol; unsigned char status; int local_variable_index_; TypeSymbol *type_; char *signature_string; }; class BlockSymbol : public Symbol { public: int max_variable_index, synchronized_variable_index, try_variable_index; BlockSymbol(int hash_size); virtual ~BlockSymbol(); int NumVariableSymbols(); VariableSymbol *VariableSym(int); inline VariableSymbol *FindVariableSymbol(NameSymbol *); inline VariableSymbol *InsertVariableSymbol(NameSymbol *); inline void InsertVariableSymbol(VariableSymbol *); inline BlockSymbol *InsertBlockSymbol(int); inline void CompressSpace(); inline SymbolTable *Table(); private: SymbolTable *table; }; class LabelSymbol : public Symbol { public: AstBlock *block; // the block that is labeled by this symbol NameSymbol *name_symbol; int nesting_level; virtual wchar_t *Name() { return name_symbol -> Name(); } virtual int NameLength() { return name_symbol -> NameLength(); } virtual NameSymbol *Identity() { return name_symbol; } char *Utf8Name() { return (char *) (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> value : NULL); } int Utf8NameLength() { return (name_symbol -> Utf8_literal ? name_symbol -> Utf8_literal -> length : 0); } LabelSymbol(NameSymbol *name_symbol_) : block(NULL), nesting_level(0), name_symbol(name_symbol_) { Symbol::_kind = LABEL; } virtual ~LabelSymbol() {} private: }; class SymbolTable { public: enum { DEFAULT_HASH_SIZE = 13, MAX_HASH_SIZE = 1021 }; int NumAnonymousSymbols() { return (anonymous_symbol_pool ? anonymous_symbol_pool -> Length() : 0); } TypeSymbol *AnonymousSym(int i) { return (*anonymous_symbol_pool)[i]; } void AddAnonymousSymbol(TypeSymbol *symbol) { if (! anonymous_symbol_pool) anonymous_symbol_pool = new ConvertibleArray<TypeSymbol *>(256); anonymous_symbol_pool -> Next() = symbol; } int NumTypeSymbols() { return (type_symbol_pool ? type_symbol_pool -> Length() : 0); } TypeSymbol *&TypeSym(int i) { return (*type_symbol_pool)[i]; } void AddTypeSymbol(TypeSymbol *symbol) { if (! type_symbol_pool) type_symbol_pool = new ConvertibleArray<TypeSymbol *>(256); type_symbol_pool -> Next() = symbol; } int NumMethodSymbols() { return (method_symbol_pool ? method_symbol_pool -> Length() : 0); } MethodSymbol *MethodSym(int i) { return (*method_symbol_pool)[i]; } void AddMethodSymbol(MethodSymbol *symbol) { if (! method_symbol_pool) method_symbol_pool = new ConvertibleArray<MethodSymbol *>(256); method_symbol_pool -> Next() = symbol; } int NumVariableSymbols() { return (variable_symbol_pool ? variable_symbol_pool -> Length() : 0); } VariableSymbol *VariableSym(int i) { return (*variable_symbol_pool)[i]; } void AddVariableSymbol(VariableSymbol *symbol) { if (! variable_symbol_pool) variable_symbol_pool = new ConvertibleArray<VariableSymbol *>(256); variable_symbol_pool -> Next() = symbol; } int NumOtherSymbols() { return (other_symbol_pool ? other_symbol_pool -> Length() : 0); } Symbol *OtherSym(int i) { return (*other_symbol_pool)[i]; } void AddOtherSymbol(Symbol *symbol) { if (! other_symbol_pool) other_symbol_pool = new ConvertibleArray<Symbol *>(256); other_symbol_pool -> Next() = symbol; } SymbolTable(int hash_size_ = DEFAULT_HASH_SIZE); ~SymbolTable(); inline void CompressSpace() { if (anonymous_symbol_pool) (void) anonymous_symbol_pool -> Array(); if (method_symbol_pool) (void) method_symbol_pool -> Array(); if (variable_symbol_pool) (void) variable_symbol_pool -> Array(); if (other_symbol_pool) (void) other_symbol_pool -> Array(); return; } private: Tuple<TypeSymbol *> *type_symbol_pool; // This array should not be convertible. See SymbolTable::DeleteTypeSymbol ConvertibleArray<TypeSymbol *> *anonymous_symbol_pool; ConvertibleArray<MethodSymbol *> *method_symbol_pool; ConvertibleArray<VariableSymbol *> *variable_symbol_pool; ConvertibleArray<Symbol *> *other_symbol_pool; Symbol **base; int hash_size; static int primes[]; int prime_index; int Size() { return NumAnonymousSymbols() + NumTypeSymbols() + NumMethodSymbols() + NumVariableSymbols() + NumOtherSymbols(); } void Rehash(); MethodSymbol *constructor; public: inline PathSymbol *InsertPathSymbol(NameSymbol *, DirectorySymbol *); inline PathSymbol *FindPathSymbol(NameSymbol *); inline DirectorySymbol *InsertDirectorySymbol(NameSymbol *, Symbol *); inline DirectorySymbol *InsertAndReadDirectorySymbol(NameSymbol *, Symbol *); inline DirectorySymbol *FindDirectorySymbol(NameSymbol *); inline FileSymbol *InsertFileSymbol(NameSymbol *); inline FileSymbol *FindFileSymbol(NameSymbol *); inline PackageSymbol *InsertPackageSymbol(NameSymbol *, PackageSymbol *); inline PackageSymbol *FindPackageSymbol(NameSymbol *); inline TypeSymbol *InsertAnonymousTypeSymbol(NameSymbol *); inline TypeSymbol *InsertSystemTypeSymbol(NameSymbol *); inline TypeSymbol *InsertOuterTypeSymbol(NameSymbol *); inline TypeSymbol *InsertNestedTypeSymbol(NameSymbol *); inline void DeleteTypeSymbol(TypeSymbol *); inline void DeleteAnonymousTypes(); inline TypeSymbol *FindTypeSymbol(NameSymbol *); inline MethodSymbol *InsertMethodSymbol(NameSymbol *); inline MethodSymbol *InsertConstructorSymbol(NameSymbol *); inline void InsertMethodSymbol(MethodSymbol *); inline void InsertConstructorSymbol(MethodSymbol *); inline MethodSymbol *FindMethodSymbol(NameSymbol *); inline MethodSymbol *FindConstructorSymbol(); inline VariableSymbol *InsertVariableSymbol(NameSymbol *); inline void InsertVariableSymbol(VariableSymbol *); inline VariableSymbol *FindVariableSymbol(NameSymbol *); inline LabelSymbol *InsertLabelSymbol(NameSymbol *); inline LabelSymbol *FindLabelSymbol(NameSymbol *); inline BlockSymbol *InsertBlockSymbol(int); inline MethodSymbol *Overload(MethodSymbol *); inline void Overload(MethodSymbol *, MethodSymbol *); inline MethodSymbol *LocalConstructorOverload(MethodSymbol *); MethodSymbol *FindOverloadMethod(MethodSymbol *, AstMethodDeclarator *); }; inline int TypeSymbol::NumVariableSymbols() { return (table ? table -> NumVariableSymbols() : 0); } inline int BlockSymbol::NumVariableSymbols() { return (table ? table -> NumVariableSymbols() : 0); } inline VariableSymbol *TypeSymbol::VariableSym(int i) { return table -> VariableSym(i); } inline VariableSymbol *BlockSymbol::VariableSym(int i) { return table -> VariableSym(i); } inline int TypeSymbol::NumMethodSymbols() { return (table ? table -> NumMethodSymbols() : 0); } inline MethodSymbol *TypeSymbol::MethodSym(int i) { return table -> MethodSym(i); } inline int TypeSymbol::NumTypeSymbols() { return (table ? table -> NumTypeSymbols() : 0); } inline TypeSymbol *TypeSymbol::TypeSym(int i) { return table -> TypeSym(i); } inline void TypeSymbol::CompressSpace() { if (table) table -> CompressSpace(); } inline void BlockSymbol::CompressSpace() { if (table) table -> CompressSpace(); } inline PathSymbol *SymbolTable::InsertPathSymbol(NameSymbol *name_symbol, DirectorySymbol *directory_symbol) { assert(base); PathSymbol *symbol = new PathSymbol(name_symbol); directory_symbol -> owner = symbol; symbol -> root_directory = directory_symbol; AddOtherSymbol(symbol); int k = name_symbol -> index % hash_size; symbol -> next = base[k]; base[k] = symbol; // // If the set is "adjustable" and the number of unique elements in it exceeds // 2 times the size of the base, and we have not yet reached the maximum // allowable size for a base, reallocate a larger base and rehash the elements. // if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1))) Rehash(); return symbol; } inline PathSymbol *SymbolTable::FindPathSymbol(NameSymbol *name_symbol) { assert(base); for (Symbol *symbol = base[name_symbol -> index % hash_size]; symbol; symbol = symbol -> next) { if (name_symbol == symbol -> Identity()) return (PathSymbol *) symbol; } return (PathSymbol *) NULL; } inline DirectorySymbol *SymbolTable::InsertDirectorySymbol(NameSymbol *name_symbol, Symbol *owner) { assert(base); DirectorySymbol *symbol = new DirectorySymbol(name_symbol, owner); AddOtherSymbol(symbol); int k = name_symbol -> index % hash_size; symbol -> next = base[k]; base[k] = symbol; // // If the set is "adjustable" and the number of unique elements in it exceeds // 2 times the size of the base, and we have not yet reached the maximum // allowable size for a base, reallocate a larger base and rehash the elements. // if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1))) Rehash(); return symbol; } inline DirectorySymbol *SymbolTable::InsertAndReadDirectorySymbol(NameSymbol *name_symbol, Symbol *owner) { DirectorySymbol *subdirectory_symbol = InsertDirectorySymbol(name_symbol, owner); subdirectory_symbol -> ResetDirectory(); return subdirectory_symbol; } inline DirectorySymbol *DirectorySymbol::InsertDirectorySymbol(NameSymbol *name_symbol) { DirectorySymbol *subdirectory_symbol = Table() -> InsertDirectorySymbol(name_symbol, this); this -> subdirectories.Next() = subdirectory_symbol; return subdirectory_symbol; } inline DirectorySymbol *DirectorySymbol::InsertAndReadDirectorySymbol(NameSymbol *name_symbol) { DirectorySymbol *subdirectory_symbol = Table() -> InsertAndReadDirectorySymbol(name_symbol, this); this -> subdirectories.Next() = subdirectory_symbol; return subdirectory_symbol; } inline DirectorySymbol *SymbolTable::FindDirectorySymbol(NameSymbol *name_symbol) { assert(base); for (Symbol *symbol = base[name_symbol -> index % hash_size]; symbol; symbol = symbol -> next) { if (name_symbol == symbol -> Identity()) { DirectorySymbol *directory_symbol = symbol -> DirectoryCast(); if (directory_symbol) return directory_symbol; } } return (DirectorySymbol *) NULL; } inline DirectorySymbol *DirectorySymbol::FindDirectorySymbol(NameSymbol *name_symbol) { return (table ? table -> FindDirectorySymbol(name_symbol) : (DirectorySymbol *) NULL); } inline FileSymbol *SymbolTable::InsertFileSymbol(NameSymbol *name_symbol) { assert(base); FileSymbol *symbol = new FileSymbol(name_symbol); AddOtherSymbol(symbol); int k = name_symbol -> index % hash_size; symbol -> next = base[k]; base[k] = symbol; // // If the set is "adjustable" and the number of unique elements in it exceeds // 2 times the size of the base, and we have not yet reached the maximum // allowable size for a base, reallocate a larger base and rehash the elements. // if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1))) Rehash(); return symbol; } inline FileSymbol *DirectorySymbol::InsertFileSymbol(NameSymbol *name_symbol) { return Table() -> InsertFileSymbol(name_symbol); } inline FileSymbol *SymbolTable::FindFileSymbol(NameSymbol *name_symbol) { assert(base); for (Symbol *symbol = base[name_symbol -> index % hash_size]; symbol; symbol = symbol -> next) { if (name_symbol == symbol -> Identity()) { FileSymbol *file_symbol = symbol -> FileCast(); if (file_symbol) return file_symbol; } } return (FileSymbol *) NULL; } inline FileSymbol *DirectorySymbol::FindFileSymbol(NameSymbol *name_symbol) { return (table ? table -> FindFileSymbol(name_symbol) : (FileSymbol *) NULL); } inline PackageSymbol *SymbolTable::InsertPackageSymbol(NameSymbol *name_symbol, PackageSymbol *owner) { assert(base); PackageSymbol *symbol = new PackageSymbol(name_symbol, owner); AddOtherSymbol(symbol); int k = name_symbol -> index % hash_size; symbol -> next = base[k]; base[k] = symbol; // // If the set is "adjustable" and the number of unique elements in it exceeds // 2 times the size of the base, and we have not yet reached the maximum // allowable size for a base, reallocate a larger base and rehash the elements. // if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1))) Rehash(); return symbol; } inline PackageSymbol *PackageSymbol::InsertPackageSymbol(NameSymbol *name_symbol) { return Table() -> InsertPackageSymbol(name_symbol, this); } inline PackageSymbol *SymbolTable::FindPackageSymbol(NameSymbol *name_symbol) { assert(base); for (Symbol *symbol = base[name_symbol -> index % hash_size]; symbol; symbol = symbol -> next) { if (name_symbol == symbol -> Identity()) { PackageSymbol *package_symbol = symbol -> PackageCast(); if (package_symbol) return package_symbol; } } return (PackageSymbol *) NULL; } inline PackageSymbol *PackageSymbol::FindPackageSymbol(NameSymbol *name_symbol) { return (table ? table -> FindPackageSymbol(name_symbol) : (PackageSymbol *) NULL); } inline TypeSymbol *SymbolTable::InsertAnonymousTypeSymbol(NameSymbol *name_symbol) { TypeSymbol *symbol = new TypeSymbol(name_symbol); AddAnonymousSymbol(symbol); return symbol; } inline TypeSymbol *TypeSymbol::InsertAnonymousTypeSymbol(NameSymbol *name_symbol) { return Table() -> InsertAnonymousTypeSymbol(name_symbol); } inline TypeSymbol *SymbolTable::InsertSystemTypeSymbol(NameSymbol *name_symbol) { assert(base); TypeSymbol *symbol = new TypeSymbol(name_symbol); symbol -> pool_index = NumTypeSymbols(); AddTypeSymbol(symbol); int k = name_symbol -> index % hash_size; symbol -> next = base[k]; base[k] = symbol; // // If the set is "adjustable" and the number of unique elements in it exceeds // 2 times the size of the base, and we have not yet reached the maximum // allowable size for a base, reallocate a larger base and rehash the elements. // if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1))) Rehash(); return symbol; } inline TypeSymbol *PackageSymbol::InsertSystemTypeSymbol(NameSymbol *name_symbol) { return Table() -> InsertSystemTypeSymbol(name_symbol); } inline TypeSymbol *SymbolTable::InsertOuterTypeSymbol(NameSymbol *name_symbol) { assert(base); TypeSymbol *symbol = new TypeSymbol(name_symbol); symbol -> pool_index = NumTypeSymbols(); AddTypeSymbol(symbol); int k = name_symbol -> index % hash_size; symbol -> next = base[k]; base[k] = symbol; // // If the set is "adjustable" and the number of unique elements in it exceeds // 2 times the size of the base, and we have not yet reached the maximum // allowable size for a base, reallocate a larger base and rehash the elements. // if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1))) Rehash(); return symbol; } inline TypeSymbol *PackageSymbol::InsertOuterTypeSymbol(NameSymbol *name_symbol) { return Table() -> InsertOuterTypeSymbol(name_symbol); } inline TypeSymbol *SymbolTable::InsertNestedTypeSymbol(NameSymbol *name_symbol) { assert(base); TypeSymbol *symbol = new TypeSymbol(name_symbol); symbol -> pool_index = NumTypeSymbols(); AddTypeSymbol(symbol); int k = name_symbol -> index % hash_size; symbol -> next = base[k]; base[k] = symbol; // // If the set is "adjustable" and the number of unique elements in it exceeds // 2 times the size of the base, and we have not yet reached the maximum // allowable size for a base, reallocate a larger base and rehash the elements. // if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1))) Rehash(); return symbol; } inline TypeSymbol *TypeSymbol::InsertNestedTypeSymbol(NameSymbol *name_symbol) { return Table() -> InsertNestedTypeSymbol(name_symbol); } inline void SymbolTable::DeleteTypeSymbol(TypeSymbol *type) { assert(base); int k = type -> name_symbol -> index % hash_size; if (type == base[k]) base[k] = type -> next; else { Symbol *previous = base[k]; for (Symbol *symbol = previous -> next; symbol != type; previous = symbol, symbol = symbol -> next) ; previous -> next = type -> next; } int last_index = NumTypeSymbols() - 1; if (type -> pool_index != last_index) {// move last element to position previously occupied by element being deleted TypeSym(last_index) -> pool_index = type -> pool_index; TypeSym(type -> pool_index) = TypeSym(last_index); } type_symbol_pool -> Reset(last_index); // remove last slot in symbol_pool delete type; return; } inline void PackageSymbol::DeleteTypeSymbol(TypeSymbol *type) { if (table) table -> DeleteTypeSymbol(type); } inline void SymbolTable::DeleteAnonymousTypes() { for (int i = 0; i < NumAnonymousSymbols(); i++) delete AnonymousSym(i); delete anonymous_symbol_pool; anonymous_symbol_pool = NULL; return; } inline void TypeSymbol::DeleteAnonymousTypes() { delete anonymous_types; anonymous_types = NULL; if (table) table -> DeleteAnonymousTypes(); } inline TypeSymbol *SymbolTable::FindTypeSymbol(NameSymbol *name_symbol) { assert(base); for (Symbol *symbol = base[name_symbol -> index % hash_size]; symbol; symbol = symbol -> next) { if (name_symbol == symbol -> Identity()) { TypeSymbol *type = symbol -> TypeCast(); if (type) return type; } } return (TypeSymbol *) NULL; } inline TypeSymbol *PackageSymbol::FindTypeSymbol(NameSymbol *name_symbol) { return (table ? table -> FindTypeSymbol(name_symbol) : (TypeSymbol *) NULL); } inline TypeSymbol *TypeSymbol::FindTypeSymbol(NameSymbol *name_symbol) { return (table ? table -> FindTypeSymbol(name_symbol) : (TypeSymbol *) NULL); } inline MethodSymbol *SymbolTable::InsertMethodSymbol(NameSymbol *name_symbol) { assert(base); MethodSymbol *symbol = new MethodSymbol(name_symbol); AddMethodSymbol(symbol); int k = name_symbol -> index % hash_size; symbol -> next = base[k]; base[k] = symbol; // // If the set is "adjustable" and the number of unique elements in it exceeds // 2 times the size of the base, and we have not yet reached the maximum // allowable size for a base, reallocate a larger base and rehash the elements. // if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1))) Rehash(); return symbol; } inline MethodSymbol *TypeSymbol::InsertMethodSymbol(NameSymbol *name_symbol) { return Table() -> InsertMethodSymbol(name_symbol); } inline MethodSymbol *SymbolTable::InsertConstructorSymbol(NameSymbol *name_symbol) { assert(! constructor); this -> constructor = InsertMethodSymbol(name_symbol); return this -> constructor; } inline MethodSymbol *TypeSymbol::InsertConstructorSymbol(NameSymbol *name_symbol) { return Table() -> InsertConstructorSymbol(name_symbol); } inline void SymbolTable::InsertMethodSymbol(MethodSymbol *method_symbol) { assert(base); AddMethodSymbol(method_symbol); int k = method_symbol -> name_symbol -> index % hash_size; method_symbol -> next = base[k]; base[k] = method_symbol; // // If the set is "adjustable" and the number of unique elements in it exceeds // 2 times the size of the base, and we have not yet reached the maximum // allowable size for a base, reallocate a larger base and rehash the elements. // if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1))) Rehash(); return; } inline void TypeSymbol::InsertMethodSymbol(MethodSymbol *method_symbol) { Table() -> InsertMethodSymbol(method_symbol); } inline void SymbolTable::InsertConstructorSymbol(MethodSymbol *method_symbol) { assert(! constructor); this -> constructor = method_symbol; InsertMethodSymbol(method_symbol); } inline void TypeSymbol::InsertConstructorSymbol(MethodSymbol *method_symbol) { Table() -> InsertConstructorSymbol(method_symbol); } inline MethodSymbol *SymbolTable::FindMethodSymbol(NameSymbol *name_symbol) { assert(base); for (Symbol *symbol = base[name_symbol -> index % hash_size]; symbol; symbol = symbol -> next) { if (name_symbol == symbol -> Identity()) { MethodSymbol *method = symbol -> MethodCast(); if (method) return method; } } return (MethodSymbol *) NULL; } inline MethodSymbol *TypeSymbol::FindMethodSymbol(NameSymbol *name_symbol) { return (table ? table -> FindMethodSymbol(name_symbol) : (MethodSymbol *) NULL); } inline MethodSymbol *SymbolTable::FindConstructorSymbol() { return this -> constructor; } inline MethodSymbol *TypeSymbol::FindConstructorSymbol() { return (table ? table -> FindConstructorSymbol() : (MethodSymbol *) NULL); } inline VariableSymbol *SymbolTable::InsertVariableSymbol(NameSymbol *name_symbol) { assert(base); VariableSymbol *symbol = new VariableSymbol(name_symbol); AddVariableSymbol(symbol); int k = name_symbol -> index % hash_size; symbol -> next = base[k]; base[k] = symbol; // // If the set is "adjustable" and the number of unique elements in it exceeds // 2 times the size of the base, and we have not yet reached the maximum // allowable size for a base, reallocate a larger base and rehash the elements. // if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1))) Rehash(); return symbol; } inline VariableSymbol *TypeSymbol::InsertVariableSymbol(NameSymbol *name_symbol) { return Table() -> InsertVariableSymbol(name_symbol); } inline VariableSymbol *BlockSymbol::InsertVariableSymbol(NameSymbol *name_symbol) { return Table() -> InsertVariableSymbol(name_symbol); } inline void SymbolTable::InsertVariableSymbol(VariableSymbol *variable_symbol) { assert(base); AddVariableSymbol(variable_symbol); int k = variable_symbol -> name_symbol -> index % hash_size; variable_symbol -> next = base[k]; base[k] = variable_symbol; // // If the set is "adjustable" and the number of unique elements in it exceeds // 2 times the size of the base, and we have not yet reached the maximum // allowable size for a base, reallocate a larger base and rehash the elements. // if ((hash_size < MAX_HASH_SIZE) && (Size() > (hash_size << 1))) Rehash(); return; } inline void TypeSymbol::InsertVariableSymbol(VariableSymbol *variable_symbol) { Table() -> InsertVariableSymbol(variable_symbol); } inline void BlockSymbol::InsertVariableSymbol(VariableSymbol *variable_symbol) { Table() -> InsertVariableSymbol(variable_symbol); } inline VariableSymbol *SymbolTable::FindVariableSymbol(NameSymbol *name_symbol) { assert(base); for (Symbol *symbol = base[name_symbol -> index % hash_size]; symbol; symbol = symbol -> next) { if (name_symbol == symbol -> Identity()) { VariableSymbol *variable_symbol = symbol -> VariableCast(); if (variable_symbol) return variable_symbol; } } return (VariableSymbol *) NULL; } inline VariableSymbol *TypeSymbol::FindVariableSymbol(NameSymbol *name_symbol) { return (table ? table -> FindVariableSymbol(name_symbol) : (VariableSymbol *) NULL); } inline VariableSymbol *BlockSymbol::FindVariableSymbol(NameSymbol *name_symbol) { return (table ? table -> FindVariableSymbol(name_symbol) : (VariableSymbol *) NULL); } inline LabelSymbol *SymbolTable::InsertLabelSymbol(NameSymbol *name_symbol) { assert(base); LabelSymbol *symbol = new LabelSymbol(name_symbol); AddOtherSymbol(symbol); int k = name_symbol -> index % hash_size; symbol -> next = base[k]; base[k] = symbol; // // as only one label can be inserted in any given symboltable, // we don't need to try to rehash here ! // return symbol; } inline LabelSymbol *SymbolTable::FindLabelSymbol(NameSymbol *name_symbol) { assert(base); for (Symbol *symbol = base[name_symbol -> index % hash_size]; symbol; symbol = symbol -> next) { if (name_symbol == symbol -> Identity()) { LabelSymbol *label = symbol -> LabelCast(); if (label) return label; } } return (LabelSymbol *) NULL; } inline BlockSymbol *SymbolTable::InsertBlockSymbol(int hash_size = 0) { BlockSymbol *symbol = new BlockSymbol(hash_size); AddOtherSymbol(symbol); return symbol; } inline BlockSymbol *BlockSymbol::InsertBlockSymbol(int hash_size = 0) { return Table() -> InsertBlockSymbol(hash_size); } inline MethodSymbol *SymbolTable::Overload(MethodSymbol *base_method) { MethodSymbol *overload = new MethodSymbol(base_method -> Identity()); AddMethodSymbol(overload); overload -> next = overload; // mark overloaded method overload -> next_method = base_method -> next_method; base_method -> next_method = overload; return overload; } inline MethodSymbol *TypeSymbol::Overload(MethodSymbol *base_method) { assert(table); return table -> Overload(base_method); } inline void SymbolTable::Overload(MethodSymbol *base_method, MethodSymbol *overload) { AddMethodSymbol(overload); overload -> next = overload; // mark overloaded method overload -> next_method = base_method -> next_method; base_method -> next_method = overload; return; } inline void TypeSymbol::Overload(MethodSymbol *base_method, MethodSymbol *overload) { assert(table); table -> Overload(base_method, overload); } inline MethodSymbol *SymbolTable::LocalConstructorOverload(MethodSymbol *base_method) { MethodSymbol *overload = new MethodSymbol(base_method -> Identity()); AddMethodSymbol(overload); overload -> next = overload; // mark overloaded method overload -> SetGeneratedLocalConstructor(base_method); return overload; } inline MethodSymbol *TypeSymbol::LocalConstructorOverload(MethodSymbol *base_method) { assert(table); return table -> LocalConstructorOverload(base_method); } inline MethodSymbol *TypeSymbol::FindOverloadMethod(MethodSymbol *base_method, AstMethodDeclarator *method_declarator) { return (table ? table -> FindOverloadMethod(base_method, method_declarator) : (MethodSymbol *) NULL); } inline SymbolTable *DirectorySymbol::Table() { return (table ? table : table = new SymbolTable(101)); } inline SymbolTable *PackageSymbol::Table() { return (table ? table : table = new SymbolTable(101)); } inline void TypeSymbol::SetSymbolTable(int estimate) { if (! table) // If table was not yet allocated, allocate one based on the estimate table = new SymbolTable(estimate); } inline SymbolTable *TypeSymbol::Table() { return (table ? table : table = new SymbolTable()); } inline SymbolTable *BlockSymbol::Table() { return (table ? table : table = new SymbolTable()); } #ifdef UNIX_FILE_SYSTEM inline bool FileSymbol::IsClassSuffix(char *suffix) { return (strncmp(suffix, class_suffix, class_suffix_length) == 0); } inline bool FileSymbol::IsJavaSuffix(char *suffix) { return (strncmp(suffix, java_suffix, java_suffix_length) == 0); } #elif defined(WIN32_FILE_SYSTEM) inline bool FileSymbol::IsClassSuffix(char *suffix) { return Case::StringSegmentEqual(suffix, class_suffix, class_suffix_length); } inline bool FileSymbol::IsJavaSuffix(char *suffix) { return Case::StringSegmentEqual(suffix, java_suffix, java_suffix_length); } #endif #endif // ifndef symbol_INCLUDED