// $Id: decl.cpp,v 1.15 1999/03/09 14:37:15 shields Exp $ copyright notice #include "config.h" #include <sys/stat.h> #include "semantic.h" #include "control.h" #include "depend.h" #include "table.h" #include "tuple.h" // // If this compilation unit contains a package declaration, make sure the package // is associated with a directory and that the name of the package is not also // associated with a type. // inline void Semantic::CheckPackage() { if (compilation_unit -> package_declaration_opt) { // // Make sure that the package actually exists. // if (this_package -> directory.Length() == 0 && control.option.directory == NULL) { ReportSemError(SemanticError::PACKAGE_NOT_FOUND, compilation_unit -> package_declaration_opt -> name -> LeftToken(), compilation_unit -> package_declaration_opt -> name -> RightToken(), this_package -> PackageName()); } else { // // Make sure that the package or any of its parents does not match the name of a type. // AstPackageDeclaration *package_declaration = compilation_unit -> package_declaration_opt; AstExpression *name = FindFirstType(package_declaration -> name); TypeSymbol *type = name -> symbol -> TypeCast(); if (type && (! type -> Bad())) { assert(type -> file_symbol); char *file_name = type -> file_symbol -> FileName(); int length = type -> file_symbol -> FileNameLength(); wchar_t *error_name = new wchar_t[length + 1]; for (int i = 0; i < length; i++) error_name[i] = file_name[i]; error_name[length] = U_NULL; ReportSemError(SemanticError::PACKAGE_TYPE_CONFLICT, name -> LeftToken(), name -> RightToken(), type -> ContainingPackage() -> PackageName(), type -> Name(), error_name); delete [] error_name; } } } return; } // // Pass 1: Introduce the main package, the current package and all types specified into their proper scope // void Semantic::ProcessTypeNames() { import_on_demand_packages.Next() = control.system_package; compilation_unit = source_file_symbol -> compilation_unit; // // If we are supposed to be verbose, report empty declarations... // if (control.option.pedantic) { if (compilation_unit -> EmptyCompilationUnitCast()) { ReportSemError(SemanticError::NO_TYPES, compilation_unit -> LeftToken(), compilation_unit -> RightToken()); } for (int i = 0; i < compilation_unit -> NumTypeDeclarations(); i++) { Ast *type_declaration = compilation_unit -> TypeDeclaration(i); if (type_declaration -> EmptyDeclarationCast()) { ReportSemError(SemanticError::EMPTY_DECLARATION, type_declaration -> LeftToken(), type_declaration -> RightToken()); } } } // // If we have a bad compilation unit insert its types as "bad types" // if (compilation_unit -> BadCompilationUnitCast()) { for (int i = 0; i < lex_stream -> NumTypes(); i++) { LexStream::TokenIndex identifier_token = lex_stream -> Next(lex_stream -> Type(i)); if (lex_stream -> Kind(identifier_token) == TK_Identifier) { NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(identifier_token); TypeSymbol *type = this_package -> FindTypeSymbol(name_symbol); assert(type); type -> MarkSourceNoLongerPending(); type -> supertypes_closure = new SymbolSet; type -> subtypes = new SymbolSet; type -> semantic_environment = new SemanticEnvironment((Semantic *) this, type, NULL); if (type != control.Object()) type -> super = (type == control.Throwable() ? control.Object() : control.Throwable()); type -> MarkBad(); AddDefaultConstructor(type); source_file_symbol -> types.Next() = type; } } return; } // // Process each type in this compilation unit, in turn // for (int k = 0; k < compilation_unit -> NumTypeDeclarations(); k++) { LexStream::TokenIndex identifier_token; TypeSymbol *type = NULL; Ast *type_declaration = compilation_unit -> TypeDeclaration(k); switch(type_declaration -> kind) { case Ast::CLASS: { AstClassDeclaration *class_declaration = (AstClassDeclaration *) type_declaration; identifier_token = class_declaration -> identifier_token; NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(identifier_token); type = this_package -> FindTypeSymbol(name_symbol); if (type) { if (! type -> SourcePending()) { ReportSemError(SemanticError::DUPLICATE_TYPE_DECLARATION, identifier_token, identifier_token, name_symbol -> Name(), type -> FileLoc()); type = NULL; } else { if (type -> ContainingPackage() == control.unnamed_package) { TypeSymbol *old_type = (TypeSymbol *) control.unnamed_package_types.Image(name_symbol); if (old_type != type) { ReportSemError(SemanticError::DUPLICATE_TYPE_DECLARATION, identifier_token, identifier_token, name_symbol -> Name(), old_type -> FileLoc()); } } type -> MarkSourceNoLongerPending(); type -> semantic_environment = new SemanticEnvironment((Semantic *) this, type, NULL); type -> supertypes_closure = new SymbolSet; type -> subtypes = new SymbolSet; type -> declaration = class_declaration; type -> SetFlags(ProcessClassModifiers(class_declaration)); // // Add 3 extra elements for padding. May need a default constructor and other support elements. // type -> SetSymbolTable(class_declaration -> class_body -> NumClassBodyDeclarations() + 3); type -> SetLocation(); source_file_symbol -> types.Next() = type; class_declaration -> semantic_environment = type -> semantic_environment; // save for processing bodies later. CheckClassMembers(type, class_declaration -> class_body); } } break; } case Ast::INTERFACE: { AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) type_declaration; identifier_token = interface_declaration -> identifier_token; NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(identifier_token); type = this_package -> FindTypeSymbol(name_symbol); if (type) { if (! type -> SourcePending()) { ReportSemError(SemanticError::DUPLICATE_TYPE_DECLARATION, identifier_token, identifier_token, name_symbol -> Name(), type -> FileLoc()); type = NULL; } else { if (type -> ContainingPackage() == control.unnamed_package) { TypeSymbol *old_type = (TypeSymbol *) control.unnamed_package_types.Image(name_symbol); if (old_type != type) { ReportSemError(SemanticError::DUPLICATE_TYPE_DECLARATION, identifier_token, identifier_token, name_symbol -> Name(), old_type -> FileLoc()); } } type -> MarkSourceNoLongerPending(); type -> semantic_environment = new SemanticEnvironment((Semantic *) this, type, NULL); type -> supertypes_closure = new SymbolSet; type -> subtypes = new SymbolSet; type -> declaration = interface_declaration; type -> file_symbol = source_file_symbol; type -> SetFlags(ProcessInterfaceModifiers(interface_declaration)); type -> SetSymbolTable(interface_declaration -> NumInterfaceMemberDeclarations()); type -> SetLocation(); source_file_symbol -> types.Next() = type; interface_declaration -> semantic_environment = type -> semantic_environment; CheckInterfaceMembers(type, interface_declaration); } } break; } } // // If we successfully processed this type, check that // . its name does not conflict with a subpackage // . if it is contained in a file with a diffent name // than its own name that there does not also exist a // (java or class) file with its name. // if (type) { NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(identifier_token); for (int i = 0; i < this_package -> directory.Length(); i++) { if (this_package -> directory[i] -> FindDirectorySymbol(name_symbol)) { char *file_name = type -> file_symbol -> FileName(); int length = type -> file_symbol -> FileNameLength(); wchar_t *error_name = new wchar_t[length + 1]; for (int j = 0; j < length; j++) error_name[j] = file_name[j]; error_name[length] = U_NULL; ReportSemError(SemanticError::PACKAGE_TYPE_CONFLICT, identifier_token, identifier_token, this_package -> PackageName(), name_symbol -> Name(), error_name); delete [] error_name; } } if (type -> Identity() != source_file_symbol -> Identity()) { PackageSymbol *package = this_package; FileSymbol *file_symbol = Control::GetJavaFile(package, type -> Identity()); if (file_symbol) { ReportSemError(SemanticError::TYPE_IN_MULTIPLE_FILES, identifier_token, identifier_token, this_package -> PackageName(), source_file_symbol -> Name(), package -> PackageName(), type -> Name()); } } } } CheckPackage(); ProcessImports(); ProcessSuperTypes(); return; } void Semantic::CheckClassMembers(TypeSymbol *containing_type, AstClassBody *class_body) { for (int i = 0; i < class_body -> NumNestedClasses(); i++) { AstClassDeclaration *class_declaration = class_body -> NestedClass(i); if (! control.option.one_one) { ReportSemError(SemanticError::ONE_ONE_FEATURE, class_declaration -> LeftToken(), class_declaration -> RightToken()); } ProcessNestedClassName(containing_type, class_declaration); } for (int j = 0; j < class_body -> NumNestedInterfaces(); j++) { AstInterfaceDeclaration *interface_declaration = class_body -> NestedInterface(j); if (! control.option.one_one) { ReportSemError(SemanticError::ONE_ONE_FEATURE, interface_declaration -> LeftToken(), interface_declaration -> RightToken()); } ProcessNestedInterfaceName(containing_type, interface_declaration); } for (int k = 0; k < class_body -> NumBlocks(); k++) { if (! control.option.one_one) { ReportSemError(SemanticError::ONE_ONE_FEATURE, class_body -> Block(k) -> LeftToken(), class_body -> Block(k) -> RightToken()); } } for (int l = 0; l < class_body -> NumEmptyDeclarations(); l++) { if (control.option.pedantic) { ReportSemError(SemanticError::EMPTY_DECLARATION, class_body -> EmptyDeclaration(l) -> LeftToken(), class_body -> EmptyDeclaration(l) -> RightToken()); } } return; } inline TypeSymbol *Semantic::FindTypeInShadow(TypeShadowSymbol *type_shadow_symbol, LexStream::TokenIndex identifier_token) { // // Recall that even an inaccessible member x of a super class (or interface) S, // in addition to not been inherited by a subclass, hides all other occurrences of x that may // appear in a super class (or super interface) of S (see 8.3). // TypeSymbol *type_symbol = type_shadow_symbol -> type_symbol; for (int i = 0; i < type_shadow_symbol -> NumConflicts(); i++) { ReportSemError(SemanticError::AMBIGUOUS_NAME, identifier_token, identifier_token, type_symbol -> Name(), type_symbol -> owner -> TypeCast() -> ContainingPackage() -> PackageName(), type_symbol -> owner -> TypeCast() -> ExternalName(), type_shadow_symbol -> Conflict(i) -> owner -> TypeCast() -> ContainingPackage() -> PackageName(), type_shadow_symbol -> Conflict(i) -> owner -> TypeCast() -> ExternalName()); } return type_symbol; } // // Look for a type within an environment stack, without regard to inheritance !!! // TypeSymbol *Semantic::FindTypeInEnvironment(SemanticEnvironment *env_stack, NameSymbol *name_symbol) { for (SemanticEnvironment *env = env_stack; env; env = env -> previous) { TypeSymbol *type = env -> symbol_table.FindTypeSymbol(name_symbol); if (type) return type; type = env -> Type() -> FindTypeSymbol(name_symbol); if (type) return type; if (name_symbol == env -> Type() -> Identity()) return env -> Type(); } return (TypeSymbol *) NULL; } void Semantic::CheckNestedTypeDuplication(SemanticEnvironment *env, LexStream::TokenIndex identifier_token) { NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(identifier_token); // // First check to see if we have a duplication at the same level... // TypeSymbol *old_type = (env -> symbol_table.Size() > 0 ? env -> symbol_table.Top() -> FindTypeSymbol(name_symbol) : env -> Type() -> FindTypeSymbol(name_symbol)); if (old_type) { ReportSemError(SemanticError::DUPLICATE_TYPE_DECLARATION, identifier_token, identifier_token, name_symbol -> Name(), old_type -> FileLoc()); } else if (env -> symbol_table.Size() > 0) { old_type = env -> symbol_table.FindTypeSymbol(name_symbol); // check the whole stack ! if (old_type) { ReportSemError(SemanticError::DUPLICATE_LOCAL_TYPE_DECLARATION, identifier_token, identifier_token, name_symbol -> Name(), old_type -> FileLoc()); } } else if (env -> Type() -> Identity() == name_symbol) { ReportSemError(SemanticError::DUPLICATE_INNER_TYPE_NAME, identifier_token, identifier_token, name_symbol -> Name(), env -> Type() -> FileLoc()); } else { // // ... Then check the enclosing environments... // for (env = env -> previous; env; env = env -> previous) { TypeSymbol *old_type = (env -> symbol_table.Size() > 0 ? env -> symbol_table.FindTypeSymbol(name_symbol) : (TypeSymbol *) NULL); if (old_type) { ReportSemError(SemanticError::DUPLICATE_LOCAL_TYPE_DECLARATION, identifier_token, identifier_token, name_symbol -> Name()); break; } else if (env -> Type() -> Identity() == name_symbol) { ReportSemError(SemanticError::DUPLICATE_INNER_TYPE_NAME, identifier_token, identifier_token, name_symbol -> Name(), env -> Type() -> FileLoc()); break; } } } return; } TypeSymbol *Semantic::ProcessNestedClassName(TypeSymbol *containing_type, AstClassDeclaration *class_declaration) { CheckNestedTypeDuplication(containing_type -> semantic_environment, class_declaration -> identifier_token); NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(class_declaration -> identifier_token); TypeSymbol *outermost_type = containing_type -> outermost_type; int length = containing_type -> ExternalNameLength() + 1 + name_symbol -> NameLength(); // +1 for $,... +1 for $ wchar_t *external_name = new wchar_t[length + 1]; // +1 for '\0'; wcscpy(external_name, containing_type -> ExternalName()); wcscat(external_name, StringConstant::US__DS_); wcscat(external_name, name_symbol -> Name()); TypeSymbol *inner_type = containing_type -> InsertNestedTypeSymbol(name_symbol); inner_type -> outermost_type = outermost_type; inner_type -> supertypes_closure = new SymbolSet; inner_type -> subtypes = new SymbolSet; inner_type -> SetExternalIdentity(control.FindOrInsertName(external_name, length)); inner_type -> semantic_environment = new SemanticEnvironment((Semantic *) this, inner_type, containing_type -> semantic_environment); inner_type -> declaration = class_declaration; inner_type -> file_symbol = source_file_symbol; inner_type -> SetFlags(containing_type -> ACC_INTERFACE() ? ProcessStaticNestedClassModifiers(class_declaration) : ProcessNestedClassModifiers(class_declaration)); inner_type -> SetOwner(containing_type); // // Add 3 extra elements for padding. May need a default constructor and other support elements. // inner_type -> SetSymbolTable(class_declaration -> class_body -> NumClassBodyDeclarations() + 3); inner_type -> SetLocation(); inner_type -> SetSignature(control); // // If not a top-level type, then add pointer to enclosing type. // if (! inner_type -> ACC_STATIC()) inner_type -> InsertThis(0); if (inner_type -> IsLocal()) { if (! outermost_type -> local) outermost_type -> local = new SymbolSet; outermost_type -> local -> AddElement(inner_type); } else { if (! outermost_type -> non_local) outermost_type -> non_local = new SymbolSet; outermost_type -> non_local -> AddElement(inner_type); } class_declaration -> semantic_environment = inner_type -> semantic_environment; // save for processing bodies later. CheckClassMembers(inner_type, class_declaration -> class_body); delete [] external_name; return inner_type; } void Semantic::CheckInterfaceMembers(TypeSymbol *containing_type, AstInterfaceDeclaration *interface_declaration) { for (int i = 0; i < interface_declaration -> NumNestedClasses(); i++) { AstClassDeclaration *class_declaration = interface_declaration -> NestedClass(i); if (! control.option.one_one) { ReportSemError(SemanticError::ONE_ONE_FEATURE, class_declaration -> LeftToken(), class_declaration -> RightToken()); } ProcessNestedClassName(containing_type, class_declaration); } for (int j = 0; j < interface_declaration -> NumNestedInterfaces(); j++) { AstInterfaceDeclaration *inner_interface_declaration = interface_declaration -> NestedInterface(j); if (! control.option.one_one) { ReportSemError(SemanticError::ONE_ONE_FEATURE, inner_interface_declaration -> LeftToken(), inner_interface_declaration -> RightToken()); } ProcessNestedInterfaceName(containing_type, inner_interface_declaration); } for (int l = 0; l < interface_declaration -> NumEmptyDeclarations(); l++) { if (control.option.pedantic) { ReportSemError(SemanticError::EMPTY_DECLARATION, interface_declaration -> EmptyDeclaration(l) -> LeftToken(), interface_declaration -> EmptyDeclaration(l) -> RightToken()); } } return; } TypeSymbol *Semantic::ProcessNestedInterfaceName(TypeSymbol *containing_type, AstInterfaceDeclaration *interface_declaration) { CheckNestedTypeDuplication(containing_type -> semantic_environment, interface_declaration -> identifier_token); NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(interface_declaration -> identifier_token); TypeSymbol *outermost_type = containing_type -> outermost_type; int length = containing_type -> ExternalNameLength() + 1 + name_symbol -> NameLength(); // +1 for $,... +1 for $ wchar_t *external_name = new wchar_t[length + 1]; // +1 for '\0'; wcscpy(external_name, containing_type -> ExternalName()); wcscat(external_name, StringConstant::US__DS_); wcscat(external_name, name_symbol -> Name()); TypeSymbol *inner_type = containing_type -> InsertNestedTypeSymbol(name_symbol); inner_type -> outermost_type = outermost_type; inner_type -> supertypes_closure = new SymbolSet; inner_type -> subtypes = new SymbolSet; inner_type -> SetExternalIdentity(control.FindOrInsertName(external_name, length)); inner_type -> semantic_environment = new SemanticEnvironment((Semantic *) this, inner_type, containing_type -> semantic_environment); inner_type -> declaration = interface_declaration; inner_type -> file_symbol = source_file_symbol; inner_type -> SetFlags(ProcessNestedInterfaceModifiers(interface_declaration)); inner_type -> SetOwner(containing_type); inner_type -> SetSymbolTable(interface_declaration -> NumInterfaceMemberDeclarations()); inner_type -> SetLocation(); inner_type -> SetSignature(control); if (inner_type -> IsLocal()) { if (! outermost_type -> local) outermost_type -> local = new SymbolSet; outermost_type -> local -> AddElement(inner_type); } else { if (! outermost_type -> non_local) outermost_type -> non_local = new SymbolSet; outermost_type -> non_local -> AddElement(inner_type); } interface_declaration -> semantic_environment = inner_type -> semantic_environment; // save for processing bodies later. CheckInterfaceMembers(inner_type, interface_declaration); delete [] external_name; return inner_type; } // // Pass 1.2: Process all import statements // void Semantic::ProcessImports() { for (int i = 0; i < compilation_unit -> NumImportDeclarations(); i++) { AstImportDeclaration *import_declaration = compilation_unit -> ImportDeclaration(i); if (import_declaration -> star_token_opt) ProcessTypeImportOnDemandDeclaration(import_declaration); else ProcessSingleTypeImportDeclaration(import_declaration); } return; } // // Pass 1.3: Process outer types in "extends" and "implements" clauses associated with the types. // void Semantic::ProcessSuperTypes() { // // Process outer type of superclasses and interfaces and make sure that compilation unit // contains exactly one public type. // TypeSymbol *public_type = NULL; for (int i = 0; i < compilation_unit -> NumTypeDeclarations(); i++) { TypeSymbol *type = NULL; Ast *type_declaration = compilation_unit -> TypeDeclaration(i); switch(type_declaration -> kind) { case Ast::CLASS: { AstClassDeclaration *class_declaration = (AstClassDeclaration *) type_declaration; if (class_declaration -> semantic_environment) { type = class_declaration -> semantic_environment -> Type(); if (class_declaration -> super_opt) { TypeSymbol *super_type = FindFirstType(class_declaration -> super_opt) -> symbol -> TypeCast(); if (super_type) super_type -> subtypes -> AddElement(type); } for (int k = 0; k < class_declaration -> NumInterfaces(); k++) { TypeSymbol *super_type = FindFirstType(class_declaration -> Interface(k)) -> symbol -> TypeCast(); if (super_type) { assert(super_type -> subtypes); super_type -> subtypes -> AddElement(type); } } ProcessOuterType(class_declaration); } break; } case Ast::INTERFACE: { AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) type_declaration; if (interface_declaration -> semantic_environment) { type = interface_declaration -> semantic_environment -> Type(); for (int k = 0; k < interface_declaration -> NumExtendsInterfaces(); k++) { TypeSymbol *super_type = FindFirstType(interface_declaration -> ExtendsInterface(k)) -> symbol -> TypeCast(); if (super_type) super_type -> subtypes -> AddElement(type); } ProcessOuterType(interface_declaration); } break; } default: break; } if (type && type -> ACC_PUBLIC()) { if (! public_type) { public_type = type; if (source_file_symbol -> Identity() != public_type -> Identity()) { if (type -> ACC_INTERFACE()) { AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) type_declaration; ReportSemError(SemanticError::MISMATCHED_TYPE_AND_FILE_NAMES, interface_declaration -> identifier_token, interface_declaration -> identifier_token, public_type -> Name()); } else { AstClassDeclaration *class_declaration = (AstClassDeclaration *) type_declaration; ReportSemError(SemanticError::MISMATCHED_TYPE_AND_FILE_NAMES, class_declaration -> identifier_token, class_declaration -> identifier_token, public_type -> Name()); } } } else { if (type -> ACC_INTERFACE()) { AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) type_declaration; ReportSemError(SemanticError::MULTIPLE_PUBLIC_TYPES, interface_declaration -> identifier_token, interface_declaration -> identifier_token, type -> Name(), public_type -> Name()); } else { AstClassDeclaration *class_declaration = (AstClassDeclaration *) type_declaration; ReportSemError(SemanticError::MULTIPLE_PUBLIC_TYPES, class_declaration -> identifier_token, class_declaration -> identifier_token, type -> Name(), public_type -> Name()); } } } } return; } void Semantic::ProcessOuterType(AstClassDeclaration *class_declaration) { TypeSymbol *type = class_declaration -> semantic_environment -> Type(); // // If a type has no super type, set it up properly in case // it is expanded prematurely by one of its dependents. // if (! class_declaration -> super_opt && class_declaration -> NumInterfaces() == 0) { if (type -> Identity() != control.object_name_symbol || type -> ContainingPackage() != control.system_package || type -> IsNested()) type -> super = control.Object(); } AstClassBody *class_body = class_declaration -> class_body; for (int i = 0; i < class_body -> NumNestedClasses(); i++) { AstClassDeclaration *inner_class_declaration = class_body -> NestedClass(i); if (inner_class_declaration -> semantic_environment) ProcessOuterType(inner_class_declaration); } for (int j = 0; j < class_body -> NumNestedInterfaces(); j++) { AstInterfaceDeclaration *inner_interface_declaration = class_body -> NestedInterface(j); if (inner_interface_declaration -> semantic_environment) ProcessOuterType(inner_interface_declaration); } return; } void Semantic::ProcessOuterType(AstInterfaceDeclaration *interface_declaration) { TypeSymbol *type = interface_declaration -> semantic_environment -> Type(); // // Set it up an interface properly in case it is // expanded prematurely by one of its dependents. // type -> super = control.Object(); for (int i = 0; i < interface_declaration -> NumNestedClasses(); i++) { AstClassDeclaration *inner_class_declaration = interface_declaration -> NestedClass(i); if (inner_class_declaration -> semantic_environment) ProcessOuterType(inner_class_declaration); } for (int j = 0; j < interface_declaration -> NumNestedInterfaces(); j++) { AstInterfaceDeclaration *inner_interface_declaration = interface_declaration -> NestedInterface(j); if (inner_interface_declaration -> semantic_environment) ProcessOuterType(inner_interface_declaration); } return; } // // Pass 2: Process "extends" and "implements" clauses associated with the types. // void Semantic::ProcessTypeHeader(AstClassDeclaration *class_declaration) { state_stack.Push(class_declaration -> semantic_environment); TypeSymbol *this_type = ThisType(); assert(! this_type -> HeaderProcessed() || this_type -> Bad()); if (! class_declaration -> super_opt) { if (this_type -> Identity() != control.object_name_symbol || this_package != control.system_package || this_type -> IsNested()) SetObjectSuperType(this_type, class_declaration -> identifier_token); } else { TypeSymbol *super_type = MustFindType(class_declaration -> super_opt); assert(this_type -> subtypes_closure); assert(! super_type -> SourcePending()); this_type -> super = super_type; if (this_type -> subtypes_closure -> IsElement(super_type)) // if there is a cycle, break it and issue an error message { this_type -> super = control.Object(); this_type -> MarkCircular(); ReportSemError(SemanticError::CIRCULAR_CLASS, class_declaration -> identifier_token, class_declaration -> super_opt -> RightToken(), this_type -> ContainingPackage() -> PackageName(), this_type -> ExternalName()); } else if (this_type -> Identity() == control.object_name_symbol && this_package == control.system_package && (! this_type -> IsNested())) { ReportSemError(SemanticError::OBJECT_WITH_SUPER_TYPE, class_declaration -> super_opt -> LeftToken(), class_declaration -> super_opt -> RightToken(), this_type -> ContainingPackage() -> PackageName(), this_type -> ExternalName()); this_type -> super = NULL; } else if (this_type -> super -> ACC_INTERFACE()) { ReportSemError(SemanticError::NOT_A_CLASS, class_declaration -> super_opt -> LeftToken(), class_declaration -> super_opt -> RightToken(), this_type -> super -> ContainingPackage() -> PackageName(), this_type -> super -> ExternalName()); SetObjectSuperType(this_type, class_declaration -> identifier_token); } else if (this_type -> super -> ACC_FINAL()) { ReportSemError(SemanticError::SUPER_IS_FINAL, class_declaration -> super_opt -> LeftToken(), class_declaration -> super_opt -> RightToken(), this_type -> super -> ContainingPackage() -> PackageName(), this_type -> super -> ExternalName()); } } for (int i = 0; i < class_declaration -> NumInterfaces(); i++) ProcessInterface(class_declaration -> Interface(i)); this_type -> MarkHeaderProcessed(); state_stack.Pop(); return; } void Semantic::ProcessTypeHeader(AstInterfaceDeclaration *interface_declaration) { state_stack.Push(interface_declaration -> semantic_environment); TypeSymbol *this_type = ThisType(); assert(! this_type -> HeaderProcessed() || this_type -> Bad()); SetObjectSuperType(this_type, interface_declaration -> identifier_token); for (int k = 0; k < interface_declaration -> NumExtendsInterfaces(); k++) ProcessInterface(interface_declaration -> ExtendsInterface(k)); assert(this_type -> subtypes_closure); for (int i = 0; i < this_type -> NumInterfaces(); i++) { if (this_type -> subtypes_closure -> IsElement(this_type -> Interface(i))) { this_type -> ResetInterfaces(); // Remove all the interfaces if a loop is detected. The error will be reported later this_type -> MarkCircular(); ReportSemError(SemanticError::CIRCULAR_INTERFACE, interface_declaration -> identifier_token, interface_declaration -> ExtendsInterface(interface_declaration -> NumExtendsInterfaces() - 1) -> RightToken(), this_type -> ContainingPackage() -> PackageName(), this_type -> ExternalName()); break; } } this_type -> MarkHeaderProcessed(); state_stack.Pop(); return; } // // Marked type and all other types that are nested inside it "circular" // void Semantic::MarkCircularNest(TypeSymbol *type) { if (type -> Circular()) return; // // Mark the type as circular // type -> MarkCircular(); type -> super = control.Object(); type -> ResetInterfaces(); // // Recursively, process any nested type... // AstClassDeclaration *class_declaration = type -> declaration -> ClassDeclarationCast(); if (class_declaration) { AstClassBody *class_body = class_declaration -> class_body; for (int i = 0; i < class_body -> NumNestedClasses(); i++) MarkCircularNest(class_body -> NestedClass(i) -> semantic_environment -> Type()); for (int k = 0; k < class_body -> NumNestedInterfaces(); k++) MarkCircularNest(class_body -> NestedInterface(k) -> semantic_environment -> Type()); } else { AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) type -> declaration; for (int i = 0; i < interface_declaration -> NumNestedClasses(); i++) MarkCircularNest(interface_declaration -> NestedClass(i) -> semantic_environment -> Type()); for (int k = 0; k < interface_declaration -> NumNestedInterfaces(); k++) MarkCircularNest(interface_declaration -> NestedInterface(k) -> semantic_environment -> Type()); } return; } // // Compute the set of super types associated with this outer-level type // and check for circularity. // void Semantic::ProcessSuperTypesOfOuterType(TypeSymbol *type) { assert((! type -> IsNested()) || type -> owner -> MethodCast()); if (type -> super) { type -> supertypes_closure -> AddElement(type -> super -> outermost_type); type -> supertypes_closure -> Union(*type -> super -> outermost_type -> supertypes_closure); } for (int k = 0; k < type -> NumInterfaces(); k++) { type -> supertypes_closure -> AddElement(type -> Interface(k) -> outermost_type); type -> supertypes_closure -> Union(*type -> Interface(k) -> outermost_type -> supertypes_closure); } SymbolSet &inner_types = *(type -> innertypes_closure); for (TypeSymbol *inner_type = (TypeSymbol *) inner_types.FirstElement(); inner_type; inner_type = (TypeSymbol *) inner_types.NextElement()) { TypeSymbol *super_type = inner_type -> super; for (int k = 0; super_type; super_type = (TypeSymbol *) (k < inner_type -> NumInterfaces() ? inner_type -> Interface(k++) : NULL)) { if (super_type -> outermost_type != type) { type -> supertypes_closure -> AddElement(super_type -> outermost_type); type -> supertypes_closure -> Union(*super_type -> outermost_type -> supertypes_closure); } } } bool circular = type -> supertypes_closure -> IsElement(type) || type -> subtypes_closure -> Intersects(*type -> supertypes_closure); if (circular) { if (type -> Circular()) // If the type is already marked circular, an error message has already been issued type -> MarkNonCircular(); // Remove the circular mark, so that we can remark the whole "nest" ? else { if (type -> ACC_INTERFACE()) { AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) type -> declaration; int right_token_index = interface_declaration -> NumExtendsInterfaces() - 1; ReportSemError(SemanticError::CIRCULAR_INTERFACE, interface_declaration -> identifier_token, (interface_declaration -> NumExtendsInterfaces() > 0 ? interface_declaration -> ExtendsInterface(right_token_index) -> RightToken() : interface_declaration -> identifier_token), type -> ContainingPackage() -> PackageName(), type -> ExternalName()); } else { AstClassDeclaration *class_declaration = (AstClassDeclaration *) type -> declaration; int right_token_index = class_declaration -> NumInterfaces() - 1; ReportSemError(SemanticError::CIRCULAR_CLASS, class_declaration -> identifier_token, (class_declaration -> NumInterfaces() > 0 ? class_declaration -> Interface(right_token_index) -> RightToken() : (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken() : class_declaration -> identifier_token)), type -> ContainingPackage() -> PackageName(), type -> ExternalName()); SetObjectSuperType(type, class_declaration -> identifier_token); assert(type -> Identity() != control.object_name_symbol || type -> ContainingPackage() != control.system_package); } } MarkCircularNest(type); } return; } // // The array partially_ordered_types contains a list of inner types. For // each of these types, compute the set of super types associated with it // and check for circularity. // void Semantic::ProcessSuperTypesOfInnerType(TypeSymbol *type, Tuple<TypeSymbol *> &partially_ordered_types) { for (int l = 0; l < partially_ordered_types.Length(); l++) { TypeSymbol *inner_type = partially_ordered_types[l]; SymbolSet &nested_types = *(inner_type -> innertypes_closure); nested_types.AddElement(inner_type); // Compute reflexive transitive closure for (TypeSymbol *nested_type = (TypeSymbol *) nested_types.FirstElement(); nested_type; nested_type = (TypeSymbol *) nested_types.NextElement()) { TypeSymbol *super_type = nested_type -> super; for (int k = 0; super_type; super_type = (TypeSymbol *) (k < nested_type -> NumInterfaces() ? nested_type -> Interface(k++) : NULL)) { for ( ; super_type; super_type = super_type -> owner -> TypeCast()) { if (type -> innertypes_closure -> IsElement(super_type)) break; } if (super_type && super_type != inner_type) { inner_type -> supertypes_closure -> AddElement(super_type); inner_type -> supertypes_closure -> Union(*super_type -> supertypes_closure); } } } bool circular = inner_type -> supertypes_closure -> IsElement(inner_type) || inner_type -> subtypes_closure -> Intersects(*inner_type -> supertypes_closure); if (circular) { MarkCircularNest(inner_type); if (inner_type -> ACC_INTERFACE()) { AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) inner_type -> declaration; ReportSemError(SemanticError::CIRCULAR_INTERFACE, interface_declaration -> identifier_token, (interface_declaration -> NumExtendsInterfaces() > 0 ? interface_declaration -> ExtendsInterface(interface_declaration -> NumExtendsInterfaces() - 1) -> RightToken() : interface_declaration -> identifier_token), inner_type -> ContainingPackage() -> PackageName(), inner_type -> ExternalName()); } else { AstClassDeclaration *class_declaration = (AstClassDeclaration *) inner_type -> declaration; ReportSemError(SemanticError::CIRCULAR_CLASS, class_declaration -> identifier_token, (class_declaration -> NumInterfaces() > 0 ? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken() : (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken() : class_declaration -> identifier_token)), inner_type -> ContainingPackage() -> PackageName(), inner_type -> ExternalName()); } } } // // At this point the innertypes_closure set contains only the // immediate inner types. // if (partially_ordered_types.Length() > 1) // inner_types set has more than one element? { SymbolSet &inner_types = *(type -> innertypes_closure); assert(partially_ordered_types.Length() == inner_types.Size()); TopologicalSort *topological_sorter = new TopologicalSort(inner_types, partially_ordered_types); topological_sorter -> Sort(); delete topological_sorter; } // // Now, complete the closure set of inner types. // for (int i = 0; i < partially_ordered_types.Length(); i++) { TypeSymbol *inner_type = partially_ordered_types[i]; type -> AddNestedType(inner_type); type -> innertypes_closure -> Union(*(inner_type -> innertypes_closure)); } return; } void Semantic::ProcessTypeHeaders(AstClassDeclaration *class_declaration) { ProcessTypeHeader(class_declaration); ProcessNestedTypeHeaders(class_declaration -> semantic_environment -> Type(), class_declaration -> class_body); ProcessSuperTypesOfOuterType(class_declaration -> semantic_environment -> Type()); return; } void Semantic::ProcessTypeHeaders(AstInterfaceDeclaration *interface_declaration) { ProcessTypeHeader(interface_declaration); ProcessNestedTypeHeaders(interface_declaration); ProcessSuperTypesOfOuterType(interface_declaration -> semantic_environment -> Type()); return; } void Semantic::ReportTypeInaccessible(LexStream::TokenIndex left_tok, LexStream::TokenIndex right_tok, TypeSymbol *type) { ReportSemError(SemanticError::TYPE_NOT_ACCESSIBLE, left_tok, right_tok, type -> ContainingPackage() -> PackageName(), type -> ExternalName(), (type -> ACC_PRIVATE() ? StringConstant::US_private : (type -> ACC_PROTECTED() ? StringConstant::US_protected : StringConstant::US_default))); return; } TypeSymbol *Semantic::FindNestedType(TypeSymbol *type, LexStream::TokenIndex identifier_token) { if (type == control.null_type || type == control.no_type || type -> Primitive()) return NULL; NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(identifier_token); if (! type -> expanded_type_table) ComputeTypesClosure(type, identifier_token); TypeShadowSymbol *type_shadow_symbol = type -> expanded_type_table -> FindTypeShadowSymbol(name_symbol); return (type_shadow_symbol ? FindTypeInShadow(type_shadow_symbol, identifier_token) : type -> FindTypeSymbol(name_symbol)); } TypeSymbol *Semantic::MustFindNestedType(TypeSymbol *type, Ast *name) { AstSimpleName *simple_name = name -> SimpleNameCast(); LexStream::TokenIndex identifier_token = (simple_name ? simple_name -> identifier_token : ((AstFieldAccess *) name) -> identifier_token); TypeSymbol *inner_type = FindNestedType(type, identifier_token); if (inner_type) TypeAccessCheck(name, inner_type); else inner_type = GetBadNestedType(type, identifier_token); return inner_type; } // // The Ast name is a qualified name (simple name or a field access). The function FindTypeInLayer // searches for the first subname that is the name of a type contained in the set inner_types. // If such a type is found, it is returned. Otherwise, the whole qualified name is resolved to // a symbol that is returned. // TypeSymbol *Semantic::FindTypeInLayer(Ast *name, SymbolSet &inner_types) { // // Unwind all the field accesses until we get to a base that is a simple name // Tuple<AstFieldAccess *> field; for (AstFieldAccess *field_access = name -> FieldAccessCast(); field_access; field_access = field_access -> base -> FieldAccessCast()) { field.Next() = field_access; name = field_access -> base; } // // If the simple_name base is a type that is an element in the inner_types set // return it. Otherwise, assume it is a package name... // AstSimpleName *simple_name = name -> SimpleNameCast(); assert(simple_name); PackageSymbol *package = NULL; TypeSymbol *type = FindType(simple_name -> identifier_token); if (type) { if (inner_types.IsElement(type)) return type; } else // If the simple_name is not a type, assume it is a package { NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(simple_name -> identifier_token); package = control.external_table.FindPackageSymbol(name_symbol); if (! package) package = control.external_table.InsertPackageSymbol(name_symbol, NULL); control.FindPathsToDirectory(package); } // // We now go through the field access in order until we either encouter a type that is an element of inner_types, // in which case, we return the type. Otherwise, we return NULL. // // for (int i = field.Length() - 1; i >= 0; i--) { AstFieldAccess *field_access = field[i]; if (type) // The base name is a type that is not contained in the inner_types set? { type = FindNestedType(type, field_access -> identifier_token); // resolve the next type... if (! type) break; if (inner_types.IsElement(type)) return type; } else { NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(field_access -> identifier_token); type = package -> FindTypeSymbol(name_symbol); if (! type) { FileSymbol *file_symbol = Control::GetFile(package, name_symbol, control.option.depend); if (file_symbol) type = ReadType(file_symbol, package, name_symbol, field_access -> identifier_token); } else if (type -> SourcePending()) control.ProcessHeaders(type -> file_symbol); // // // if (type) { if (inner_types.IsElement(type)) return type; } else // If the field access was not resolved to a type assume it is a package { NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(field_access -> identifier_token); PackageSymbol *subpackage = package -> FindPackageSymbol(name_symbol); if (! subpackage) subpackage = package -> InsertPackageSymbol(name_symbol); control.FindPathsToDirectory(subpackage); package = subpackage; } } } return NULL; } void Semantic::ProcessNestedSuperTypes(TypeSymbol *type) { int num_inner_types = type -> innertypes_closure -> Size(); if (num_inner_types > 0) { SymbolSet &inner_types = *(type -> innertypes_closure); for (TypeSymbol *inner_type = (TypeSymbol *) inner_types.FirstElement(); inner_type; inner_type = (TypeSymbol *) inner_types.NextElement()) { if (inner_type -> ACC_INTERFACE()) { AstInterfaceDeclaration *inner_interface_declaration = (AstInterfaceDeclaration *) inner_type -> declaration; for (int l = 0; l < inner_interface_declaration -> NumExtendsInterfaces(); l++) { AstExpression *interface_name = inner_interface_declaration -> ExtendsInterface(l); TypeSymbol *super_type = FindTypeInLayer(interface_name, inner_types); if (super_type) super_type -> subtypes -> AddElement(inner_type); } } else { AstClassDeclaration *inner_class_declaration = (AstClassDeclaration *) inner_type -> declaration; if (inner_class_declaration -> super_opt) { TypeSymbol *super_type = FindTypeInLayer(inner_class_declaration -> super_opt, inner_types); if (super_type) super_type -> subtypes -> AddElement(inner_type); } for (int l = 0; l < inner_class_declaration -> NumInterfaces(); l++) { TypeSymbol *super_type = FindTypeInLayer(inner_class_declaration -> Interface(l), inner_types); if (super_type) super_type -> subtypes -> AddElement(inner_type); } } } // // Create a partial order or the inner types. If there are cycles, // then the order is arbitrary. // Tuple<TypeSymbol *> partially_ordered_types; if (num_inner_types > 0) // inner_types set is not empty? { TypeCycleChecker *cycle_checker = new TypeCycleChecker(partially_ordered_types); cycle_checker -> PartialOrder(inner_types); delete cycle_checker; } for (int k = 0; k < partially_ordered_types.Length(); k++) { TypeSymbol *inner_type = partially_ordered_types[k]; if (inner_type -> ACC_INTERFACE()) { AstInterfaceDeclaration *inner_interface_declaration = (AstInterfaceDeclaration *) inner_type -> declaration; ProcessTypeHeader(inner_interface_declaration); ProcessNestedTypeHeaders(inner_interface_declaration); } else { AstClassDeclaration *inner_class_declaration = (AstClassDeclaration *) inner_type -> declaration; ProcessTypeHeader(inner_class_declaration); ProcessNestedTypeHeaders(inner_class_declaration -> semantic_environment -> Type(), inner_class_declaration -> class_body); } } ProcessSuperTypesOfInnerType(type, partially_ordered_types); } return; } void Semantic::ProcessNestedTypeHeaders(TypeSymbol *type, AstClassBody *class_body) { if (type -> expanded_type_table && (type -> super != control.Object() || type -> NumInterfaces() > 0)) { delete type -> expanded_type_table; type -> expanded_type_table = NULL; } if (! type -> expanded_type_table) ComputeTypesClosure(type, class_body -> left_brace_token); state_stack.Push(type -> semantic_environment); type -> innertypes_closure = new SymbolSet; for (int i = 0; i < class_body -> NumNestedClasses(); i++) { if (class_body -> NestedClass(i) -> semantic_environment) type -> innertypes_closure -> AddElement(class_body -> NestedClass(i) -> semantic_environment -> Type()); } for (int j = 0; j < class_body -> NumNestedInterfaces(); j++) { if (class_body -> NestedInterface(j) -> semantic_environment) type -> innertypes_closure -> AddElement(class_body -> NestedInterface(j) -> semantic_environment -> Type()); } ProcessNestedSuperTypes(type); state_stack.Pop(); return; } void Semantic::ProcessNestedTypeHeaders(AstInterfaceDeclaration *interface_declaration) { TypeSymbol *type = interface_declaration -> semantic_environment -> Type(); if (type -> expanded_type_table && type -> NumInterfaces() > 0) { delete type -> expanded_type_table; type -> expanded_type_table = NULL; } if (! type -> expanded_type_table) ComputeTypesClosure(type, interface_declaration -> identifier_token); state_stack.Push(interface_declaration -> semantic_environment); type -> innertypes_closure = new SymbolSet; for (int i = 0; i < interface_declaration -> NumNestedClasses(); i++) { if (interface_declaration -> NestedClass(i) -> semantic_environment) type -> innertypes_closure -> AddElement(interface_declaration -> NestedClass(i) -> semantic_environment -> Type()); } for (int j = 0; j < interface_declaration -> NumNestedInterfaces(); j++) { if (interface_declaration -> NestedInterface(j) -> semantic_environment) type -> innertypes_closure -> AddElement(interface_declaration -> NestedInterface(j) -> semantic_environment -> Type()); } ProcessNestedSuperTypes(type); state_stack.Pop(); return; } // // Pass 3: Process all method and constructor declarations within the compilation unit so that // any field initialization enclosed in the compilation unit can invoke any constructor or // method within the unit. // inline void Semantic::ProcessConstructorMembers(AstClassBody *class_body) { TypeSymbol *this_type = ThisType(); assert(this_type -> HeaderProcessed()); // // If the class contains no constructor, ... // if (class_body -> NumConstructors() > 0) { for (int k = 0; k < class_body -> NumConstructors(); k++) ProcessConstructorDeclaration(class_body -> Constructor(k)); } else if (! this_type -> Anonymous()) AddDefaultConstructor(this_type); this_type -> MarkConstructorMembersProcessed(); return; } inline void Semantic::ProcessMethodMembers(AstClassBody *class_body) { assert(ThisType() -> HeaderProcessed()); for (int k = 0; k < class_body -> NumMethods(); k++) ProcessMethodDeclaration(class_body -> Method(k)); ThisType() -> MarkMethodMembersProcessed(); return; } inline void Semantic::ProcessFieldMembers(AstClassBody *class_body) { assert(ThisType() -> HeaderProcessed()); for (int i = 0; i < class_body -> NumInstanceVariables(); i++) ProcessFieldDeclaration(class_body -> InstanceVariable(i)); for (int k = 0; k < class_body -> NumClassVariables(); k++) ProcessFieldDeclaration(class_body -> ClassVariable(k)); ThisType() -> MarkFieldMembersProcessed(); return; } void Semantic::ProcessMembers(SemanticEnvironment *environment, AstClassBody *class_body) { // // // state_stack.Push(environment); TypeSymbol *this_type = ThisType(); assert(! this_type -> ConstructorMembersProcessed() || this_type -> Bad()); assert(! this_type -> MethodMembersProcessed() || this_type -> Bad()); assert(! this_type -> FieldMembersProcessed() || this_type -> Bad()); ProcessConstructorMembers(class_body); ProcessMethodMembers(class_body); ProcessFieldMembers(class_body); delete this_type -> innertypes_closure; // save some space !!! this_type -> innertypes_closure = NULL; if (! this_type -> IsTopLevel()) { for (int i = 0; i < class_body -> NumStaticInitializers(); i++) { ReportSemError(SemanticError::STATIC_INITIALIZER_IN_INNER_CLASS, class_body -> StaticInitializer(i) -> LeftToken(), class_body -> StaticInitializer(i) -> RightToken(), this_type -> Name(), this_type -> FileLoc()); } } for (int i = 0; i < this_type -> NumNestedTypes(); i++) { TypeSymbol *inner_type = this_type -> NestedType(i); if (inner_type -> ACC_INTERFACE()) { AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) inner_type -> declaration; ProcessMembers(interface_declaration); if (! this_type -> IsTopLevel()) { // // TODO: 1.1 assumption // // As every field in an interface is static, we presume that all interfaces // should be treated as static entities // if (interface_declaration -> semantic_environment) { ReportSemError(SemanticError::STATIC_TYPE_IN_INNER_CLASS, interface_declaration -> identifier_token, interface_declaration -> identifier_token, lex_stream -> Name(interface_declaration -> identifier_token), this_type -> Name(), this_type -> FileLoc()); } } } else { AstClassDeclaration *class_declaration = (AstClassDeclaration *) inner_type -> declaration; ProcessMembers(class_declaration -> semantic_environment, class_declaration -> class_body); if (! this_type -> IsTopLevel()) { if (class_declaration -> semantic_environment && class_declaration -> semantic_environment -> Type() -> ACC_STATIC()) { ReportSemError(SemanticError::STATIC_TYPE_IN_INNER_CLASS, class_declaration -> identifier_token, class_declaration -> identifier_token, lex_stream -> Name(class_declaration -> identifier_token), this_type -> Name(), this_type -> FileLoc()); } } } } state_stack.Pop(); return; } inline void Semantic::ProcessMethodMembers(AstInterfaceDeclaration *interface_declaration) { assert(ThisType() -> HeaderProcessed()); for (int k = 0; k < interface_declaration -> NumMethods(); k++) ProcessMethodDeclaration(interface_declaration -> Method(k)); ThisType() -> MarkMethodMembersProcessed(); return; } inline void Semantic::ProcessFieldMembers(AstInterfaceDeclaration *interface_declaration) { assert(ThisType() -> HeaderProcessed()); for (int k = 0; k < interface_declaration -> NumClassVariables(); k++) ProcessFieldDeclaration(interface_declaration -> ClassVariable(k)); ThisType() -> MarkFieldMembersProcessed(); return; } void Semantic::ProcessMembers(AstInterfaceDeclaration *interface_declaration) { // // // state_stack.Push(interface_declaration -> semantic_environment); TypeSymbol *this_type = ThisType(); assert(! this_type -> MethodMembersProcessed() || this_type -> Bad()); assert(! this_type -> FieldMembersProcessed() || this_type -> Bad()); ProcessMethodMembers(interface_declaration); ProcessFieldMembers(interface_declaration); delete this_type -> innertypes_closure; // save some space !!! this_type -> innertypes_closure = NULL; for (int i = 0; i < this_type -> NumNestedTypes(); i++) { TypeSymbol *inner_type = this_type -> NestedType(i); if (inner_type -> ACC_INTERFACE()) { AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) inner_type -> declaration; ProcessMembers(interface_declaration); } else { AstClassDeclaration *class_declaration = (AstClassDeclaration *) inner_type -> declaration; ProcessMembers(class_declaration -> semantic_environment, class_declaration -> class_body); } } state_stack.Pop(); return; } // // Pass 4: Process the field declarations at the top level of the types // void Semantic::CompleteSymbolTable(SemanticEnvironment *environment, LexStream::TokenIndex identifier_token, AstClassBody *class_body) { if (compilation_unit -> BadCompilationUnitCast()) return; state_stack.Push(environment); TypeSymbol *this_type = ThisType(); assert(this_type -> ConstructorMembersProcessed()); assert(this_type -> MethodMembersProcessed()); assert(this_type -> FieldMembersProcessed()); // // // if (! this_type -> expanded_method_table) ComputeMethodsClosure(this_type, identifier_token); ExpandedMethodTable &expanded_table = *(this_type -> expanded_method_table); if (! this_type -> ACC_ABSTRACT()) { // // Check that every abstract method that is inherited is overridden. // for (int i = 0; i < expanded_table.symbol_pool.Length(); i++) { MethodSymbol *method = expanded_table.symbol_pool[i] -> method_symbol; if (method -> ACC_ABSTRACT()) { TypeSymbol *containing_type = method -> containing_type; if (containing_type != this_type) { // // If the method is contained in an abstract method read from a class file, // then it is possible that the abstract method is just out-of-date and needs // to be recompiled. // ReportSemError((! containing_type -> ACC_INTERFACE()) && (containing_type -> file_symbol && containing_type -> file_symbol -> IsClass()) ? SemanticError::NON_ABSTRACT_TYPE_INHERITS_ABSTRACT_METHOD_FROM_ABSTRACT_CLASS : SemanticError::NON_ABSTRACT_TYPE_INHERITS_ABSTRACT_METHOD, identifier_token, identifier_token, method -> Header((Semantic *) this, identifier_token), containing_type -> ContainingPackage() -> PackageName(), containing_type -> ExternalName(), this_type -> ContainingPackage() -> PackageName(), this_type -> ExternalName()); } } } // // If the super class of this_type is abstract and it is contained in a // different package, check to see if its members include abstract methods // with default access. If so, we must issue error messages for them also // as they cannot be overridden. // if (this_type != control.Object() && this_type -> super -> ACC_ABSTRACT() && (this_type -> ContainingPackage() != this_type -> super -> ContainingPackage())) { ExpandedMethodTable &super_expanded_table = *(this_type -> super -> expanded_method_table); for (int i = 0; i < super_expanded_table.symbol_pool.Length(); i++) { MethodSymbol *method = super_expanded_table.symbol_pool[i] -> method_symbol; if (method -> ACC_ABSTRACT() && (! (method -> ACC_PUBLIC() || method -> ACC_PROTECTED() || method -> ACC_PRIVATE()))) { TypeSymbol *containing_type = method -> containing_type; // // If the method is contained in an abstract type read from a class file, // then it is possible that the abstract method is just out-of-date and needs // to be recompiled. // ReportSemError(SemanticError::NON_ABSTRACT_TYPE_CANNOT_OVERRIDE_DEFAULT_ABSTRACT_METHOD, identifier_token, identifier_token, method -> Header((Semantic *) this, identifier_token), containing_type -> ContainingPackage() -> PackageName(), containing_type -> ExternalName(), this_type -> ContainingPackage() -> PackageName(), this_type -> ExternalName()); } } } } for (int i = 0; i < expanded_table.symbol_pool.Length(); i++) { MethodShadowSymbol *method_shadow = expanded_table.symbol_pool[i]; if (method_shadow -> NumConflicts() > 0) { MethodSymbol *method = method_shadow -> method_symbol; if (method -> containing_type == this_type) { AstMethodDeclaration *method_declaration = (AstMethodDeclaration *) method -> method_or_constructor_declaration; for (int k = 0; k < method_shadow -> NumConflicts(); k++) { MethodSymbol *hidden_method = method_shadow -> Conflict(k); if (method -> containing_type != hidden_method -> containing_type) // the methods are not in the same type CheckMethodOverride(method_declaration, hidden_method); } } else { AstClassDeclaration *class_declaration = (AstClassDeclaration *) this_type -> declaration; for (int k = 0; k < method_shadow -> NumConflicts(); k++) { MethodSymbol *hidden_method = method_shadow -> Conflict(k); if (method -> containing_type != hidden_method -> containing_type) // the methods are not in the same type CheckMethodOverride(class_declaration, method, hidden_method); } if (! method -> ACC_ABSTRACT()) { if (method -> ACC_STATIC()) { ReportSemError(SemanticError::STATIC_OVERRIDE_ABSTRACT_EXTERNALLY, class_declaration -> identifier_token, (class_declaration -> NumInterfaces() > 0 ? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken() : (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken() : class_declaration -> identifier_token)), lex_stream -> Name(class_declaration -> identifier_token), method -> Header((Semantic *) this, identifier_token), method -> containing_type -> ContainingPackage() -> PackageName(), method -> containing_type -> ExternalName(), method_shadow -> Conflict(0) -> Header((Semantic *) this, identifier_token), method_shadow -> Conflict(0) -> containing_type -> ContainingPackage() -> PackageName(), method_shadow -> Conflict(0) -> containing_type -> ExternalName()); } } } method_shadow -> RemoveConflicts(); } } ProcessStaticInitializers(class_body); ProcessBlockInitializers(class_body); // // Reset the this_variable and this_method may have been set in // ProcessStaticInitializers and/or ProcessBlockInitializers. // Indicate that there is no method being currently compiled // in this environment. // ThisVariable() = NULL; ThisMethod() = NULL; // // Recursively process all inner types // for (int l = 0; l < this_type -> NumNestedTypes(); l++) { TypeSymbol *inner_type = this_type -> NestedType(l); if (inner_type -> ACC_INTERFACE()) CompleteSymbolTable((AstInterfaceDeclaration *) inner_type -> declaration); else { AstClassDeclaration *class_declaration = (AstClassDeclaration *) inner_type -> declaration; CompleteSymbolTable(class_declaration -> semantic_environment, class_declaration -> identifier_token, class_declaration -> class_body); } } state_stack.Pop(); return; } void Semantic::CompleteSymbolTable(AstInterfaceDeclaration *interface_declaration) { if (compilation_unit -> BadCompilationUnitCast()) return; state_stack.Push(interface_declaration -> semantic_environment); TypeSymbol *this_type = ThisType(); assert(this_type -> MethodMembersProcessed()); assert(this_type -> FieldMembersProcessed()); // // // if (! this_type -> expanded_method_table) ComputeMethodsClosure(this_type, interface_declaration -> identifier_token); ExpandedMethodTable &expanded_table = *(this_type -> expanded_method_table); for (int i = 0; i < interface_declaration -> NumMethods(); i++) { AstMethodDeclaration *method_declaration = interface_declaration -> Method(i); MethodSymbol *method = method_declaration -> method_symbol; if (method) { MethodShadowSymbol *method_shadow = expanded_table.FindOverloadMethodShadow(method, (Semantic *) this, interface_declaration -> identifier_token); for (int k = 0; k < method_shadow -> NumConflicts(); k++) { if (method_shadow -> method_symbol -> Type() != method_shadow -> Conflict(k) -> Type()) { LexStream::TokenIndex token_location = method_declaration -> method_declarator -> identifier_token; ReportSemError(SemanticError::MISMATCHED_INHERITED_METHOD, method_declaration -> method_declarator -> LeftToken(), method_declaration -> method_declarator -> RightToken(), method_shadow -> method_symbol -> Header((Semantic *) this, token_location), method_shadow -> Conflict(k) -> Header((Semantic *) this, token_location), method_shadow -> Conflict(k) -> containing_type -> ContainingPackage() -> PackageName(), method_shadow -> Conflict(k) -> containing_type -> ExternalName()); } if (method_shadow -> method_symbol -> containing_type == this_type) // override ? CheckInheritedMethodThrows(method_declaration, method_shadow -> Conflict(k)); } } } // // Compute the set of final variables (all fields in an interface are final) in this type. // Tuple<VariableSymbol *> finals(this_type -> NumVariableSymbols()); for (int j = 0; j < this_type -> NumVariableSymbols(); j++) { VariableSymbol *variable_symbol = this_type -> VariableSym(j); finals.Next() = variable_symbol; } // // Initialize each variable, in turn // for (int k = 0; k < interface_declaration -> NumClassVariables(); k++) InitializeVariable(interface_declaration -> ClassVariable(k), finals); // // Recursively process all inner types // for (int l = 0; l < this_type -> NumNestedTypes(); l++) { TypeSymbol *inner_type = this_type -> NestedType(l); if (inner_type -> ACC_INTERFACE()) CompleteSymbolTable((AstInterfaceDeclaration *) inner_type -> declaration); else { AstClassDeclaration *class_declaration = (AstClassDeclaration *) inner_type -> declaration; CompleteSymbolTable(class_declaration -> semantic_environment, class_declaration -> identifier_token, class_declaration -> class_body); } } state_stack.Pop(); return; } // // Pass 5: Free up unneeded space. // void Semantic::CleanUp() { for (int i = 0; i < compilation_unit -> NumTypeDeclarations(); i++) { TypeSymbol *type = NULL; Ast *type_declaration = compilation_unit -> TypeDeclaration(i); switch(type_declaration -> kind) { case Ast::CLASS: { AstClassDeclaration *class_declaration = (AstClassDeclaration *) type_declaration; if (class_declaration -> semantic_environment) type = class_declaration -> semantic_environment -> Type(); break; } case Ast::INTERFACE: { AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) type_declaration; if (interface_declaration -> semantic_environment) type = interface_declaration -> semantic_environment -> Type(); break; } } if (type) CleanUpType(type); } return; } void Semantic::CleanUpType(TypeSymbol *type) { type -> DeleteAnonymousTypes(); for (int i = 0; i < type -> NumNestedTypes(); i++) CleanUpType(type -> NestedType(i)); type -> CompressSpace(); // space optimization for (int j = 0; j < type -> NumMethodSymbols(); j++) type -> MethodSym(j) -> CleanUp(); delete type -> local; type -> local = NULL; delete type -> non_local; type -> non_local = NULL; delete type -> semantic_environment; type -> semantic_environment = NULL; type -> declaration = NULL; return; } // // // void Semantic::ConvertUtf8ToUnicode(wchar_t *target, char *source, int len) { for (int i = 0; i < len; i++, target++) { u1 ch = source[i]; if ((ch & 0x80) == 0) *target = ch; else if ((ch & 0xE0) == 0xC0) { *target = ch & 0x1F; *target <<= 6; i++; ch = source[i] & 0x3F; *target += ch; } else if ((ch & 0xF0) == 0xE0) { *target = ch & 0x0F; *target <<= 6; i++; ch = source[i] & 0x3F; *target += ch; *target <<= 6; i++; ch = source[i] & 0x3F; *target += ch; } else { cerr << "chaos: Damn, Caramba, Zut !!!\n"; } } *target = U_NULL; return; } TypeSymbol *Semantic::ReadType(FileSymbol *file_symbol, PackageSymbol *package, NameSymbol *name_symbol, LexStream::TokenIndex tok) { TypeSymbol *type; if (file_symbol && file_symbol -> IsJava()) { if (! file_symbol -> semantic) control.ProcessHeaders(file_symbol); type = package -> FindTypeSymbol(name_symbol); if (! type) { type = package -> InsertOuterTypeSymbol(name_symbol); type -> outermost_type = type; type -> supertypes_closure = new SymbolSet; type -> subtypes = new SymbolSet; type -> semantic_environment = new SemanticEnvironment((Semantic *) this, type, NULL); if (type != control.Object()) type -> super = (type == control.Throwable() ? control.Object() : control.Throwable()); type -> SetOwner(package); type -> SetSignature(control); type -> MarkBad(); AddDefaultConstructor(type); type -> file_symbol = file_symbol; file_symbol -> types.Next() = type; ReportSemError(SemanticError::TYPE_NOT_FOUND, tok, tok, type -> ContainingPackage() -> PackageName(), type -> ExternalName()); } } else // Read class file. { type = package -> InsertOuterTypeSymbol(name_symbol); type -> outermost_type = type; type -> supertypes_closure = new SymbolSet; type -> subtypes = new SymbolSet; type -> SetOwner(package); type -> SetSignature(control); if (file_symbol) { type -> file_symbol = file_symbol; type -> SetLocation(); file_symbol -> package = package; file_symbol -> types.Next() = type; ReadClassFile(type, tok); assert (! type -> IsNested()); control.input_class_file_set.AddElement(file_symbol); } else { control.ProcessBadType(type); if (type != control.Object()) type -> super = (type == control.Throwable() ? control.Object() : control.Throwable()); type -> MarkBad(); AddDefaultConstructor(type); ReportSemError(SemanticError::TYPE_NOT_FOUND, tok, tok, type -> ContainingPackage() -> PackageName(), type -> ExternalName()); if (package == control.unnamed_package) { TypeSymbol *old_type = (TypeSymbol *) control.unnamed_package_types.Image(type -> Identity()); if (! old_type) control.unnamed_package_types.AddElement(type); else { ReportSemError(SemanticError::DUPLICATE_TYPE_DECLARATION, tok, tok, type -> Name(), old_type -> FileLoc()); } } } } return type; } TypeSymbol *Semantic::GetBadNestedType(TypeSymbol *type, LexStream::TokenIndex identifier_token) { NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(identifier_token); TypeSymbol *outermost_type = type -> outermost_type; if (! outermost_type -> non_local) outermost_type -> non_local = new SymbolSet; if (! outermost_type -> local) outermost_type -> local = new SymbolSet; int length = type -> ExternalNameLength() + 1 + name_symbol -> NameLength(); // +1 for $,... +1 for $ wchar_t *external_name = new wchar_t[length + 1]; // +1 for '\0'; wcscpy(external_name, type -> ExternalName()); wcscat(external_name, StringConstant::US__DS_); wcscat(external_name, name_symbol -> Name()); TypeSymbol *inner_type = type -> InsertNestedTypeSymbol(name_symbol); inner_type -> outermost_type = type -> outermost_type; inner_type -> supertypes_closure = new SymbolSet; inner_type -> subtypes = new SymbolSet; inner_type -> SetExternalIdentity(control.FindOrInsertName(external_name, length)); inner_type -> semantic_environment = new SemanticEnvironment((Semantic *) this, inner_type, type -> semantic_environment); inner_type -> super = control.Object(); inner_type -> SetOwner(type); inner_type -> SetSignature(control); inner_type -> InsertThis(0); inner_type -> MarkBad(); AddDefaultConstructor(inner_type); ReportSemError(SemanticError::TYPE_NOT_FOUND, identifier_token, identifier_token, inner_type -> ContainingPackage() -> PackageName(), inner_type -> ExternalName()); delete [] external_name; return inner_type; } Symbol *Semantic::ProcessImportQualifiedName(AstExpression *name) { PackageSymbol *package = NULL; TypeSymbol *type = NULL; AstFieldAccess *field_access = name -> FieldAccessCast(); if (field_access) { Symbol *symbol = ProcessImportQualifiedName(field_access -> base); type = symbol -> TypeCast(); if (type) // The base name is a type { if (! type -> NestedTypesProcessed()) type -> ProcessNestedTypeSignatures((Semantic *) this, field_access -> identifier_token); NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(field_access -> identifier_token); TypeSymbol *inner_type = type -> FindTypeSymbol(name_symbol); if (! inner_type) inner_type = GetBadNestedType(type, field_access -> identifier_token); else if (! (inner_type -> ACC_PUBLIC() || inner_type -> ContainingPackage() == this_package)) ReportTypeInaccessible(field_access, inner_type); type = inner_type; field_access -> symbol = type; // save the type to which this expression was resolved for later use... } else { package = symbol -> PackageCast(); NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(field_access -> identifier_token); type = package -> FindTypeSymbol(name_symbol); if (! type) { FileSymbol *file_symbol = Control::GetFile(package, name_symbol, control.option.depend); if (file_symbol) type = ReadType(file_symbol, package, name_symbol, field_access -> identifier_token); } else if (type -> SourcePending()) control.ProcessHeaders(type -> file_symbol); // // If the field_access was resolved to a type, save it later use. // Otherwise, assume the field_access is a package name. // if (type) field_access -> symbol = type; else { NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(field_access -> identifier_token); PackageSymbol *subpackage = package -> FindPackageSymbol(name_symbol); if (! subpackage) subpackage = package -> InsertPackageSymbol(name_symbol); control.FindPathsToDirectory(subpackage); package = subpackage; } } } else { AstSimpleName *simple_name = name -> SimpleNameCast(); assert(simple_name); // // From the 1.1 document: // // Nested classes of all sorts (top-level or inner) can be imported by either kind of // import statement. Class names in import statements must be fully package // qualified, and be resolvable without reference to inheritance relations... // if (compilation_unit -> package_declaration_opt) { type = FindSimpleNameType(this_package, simple_name -> identifier_token); // // If the type was not found, look for it in the unnamed package. // The relevant passages that justify this lookup are: // 6.5.4.11, 6.7, 7.4.2, 7.5.1 // if (! type) type = FindSimpleNameType(control.unnamed_package, simple_name -> identifier_token); } else type = FindSimpleNameType(control.unnamed_package, simple_name -> identifier_token); // // If the simple_name is a type, save it. Otherwise, assume it is a package // if (type) { if (! (type -> ACC_PUBLIC() || type -> ContainingPackage() == this_package)) ReportTypeInaccessible(name, type); simple_name -> symbol = type; } else { NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(simple_name -> identifier_token); package = control.external_table.FindPackageSymbol(name_symbol); if (! package) package = control.external_table.InsertPackageSymbol(name_symbol, NULL); control.FindPathsToDirectory(package); } } return (type ? (Symbol *) type : (Symbol *) package); } Symbol *Semantic::ProcessPackageOrType(AstExpression *name) { PackageSymbol *package = NULL; TypeSymbol *type = NULL; AstFieldAccess *field_access = name -> FieldAccessCast(); if (field_access) { Symbol *symbol = ProcessPackageOrType(field_access -> base); type = symbol -> TypeCast(); if (type) // The base name is a type { type = MustFindNestedType(type, field_access); field_access -> symbol = type; // save the type to which this expression was resolved for later use... } else { package = symbol -> PackageCast(); NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(field_access -> identifier_token); type = package -> FindTypeSymbol(name_symbol); if (! type) { FileSymbol *file_symbol = Control::GetFile(package, name_symbol, control.option.depend); if (file_symbol) type = ReadType(file_symbol, package, name_symbol, field_access -> identifier_token); } else if (type -> SourcePending()) control.ProcessHeaders(type -> file_symbol); // // If the field access was resolved into a type, then save it. // Otherwise, assume it is a package // if (type) field_access -> symbol = type; // save the type to which this expression was resolved for later use... else { NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(field_access -> identifier_token); PackageSymbol *subpackage = package -> FindPackageSymbol(name_symbol); if (! subpackage) subpackage = package -> InsertPackageSymbol(name_symbol); control.FindPathsToDirectory(subpackage); package = subpackage; } } } else { AstSimpleName *simple_name = name -> SimpleNameCast(); assert(simple_name); type = FindType(simple_name -> identifier_token); if (type) { TypeAccessCheck(simple_name, type); simple_name -> symbol = type; } else { NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(simple_name -> identifier_token); package = control.external_table.FindPackageSymbol(name_symbol); if (! package) package = control.external_table.InsertPackageSymbol(name_symbol, NULL); control.FindPathsToDirectory(package); } } return (type ? (Symbol *) type : (Symbol *) package); } void Semantic::ProcessTypeImportOnDemandDeclaration(AstImportDeclaration *import_declaration) { Symbol *symbol = ProcessImportQualifiedName(import_declaration -> name); PackageSymbol *package = symbol -> PackageCast(); if (package && package -> directory.Length() == 0) { ReportSemError(SemanticError::PACKAGE_NOT_FOUND, import_declaration -> name -> LeftToken(), import_declaration -> name -> RightToken(), package -> PackageName()); } // // Two or more type-import-on-demand may name the same package; the effect is as if there // were only one such declaration. // for (int i = 0; i < import_on_demand_packages.Length(); i++) { if (symbol == import_on_demand_packages[i]) return; } import_on_demand_packages.Next() = symbol; return; } // // The Ast name is a name expression (either a qualified name or a simplename) // FindFirstType traverses the name tree and returns the first subtree that it // finds that matches a type. As a side-effect, each subtree that matches a package // or a type has that package or type recorded in its "symbol" field. // AstExpression *Semantic::FindFirstType(Ast *name) { AstExpression *name_expression = NULL; AstFieldAccess *field_access = name -> FieldAccessCast(); if (field_access) { AstExpression *expr = FindFirstType(field_access -> base); if (expr -> symbol -> TypeCast()) // A subexpression has been found, pass it up name_expression = expr; else { PackageSymbol *package = expr -> symbol -> PackageCast(); assert(package); name_expression = field_access; // The relevant subexpression might be this field access... NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(field_access -> identifier_token); TypeSymbol *type = package -> FindTypeSymbol(name_symbol); if (type) { if (type -> SourcePending()) control.ProcessHeaders(type -> file_symbol); field_access -> symbol = type; } else { FileSymbol *file_symbol = Control::GetFile(package, name_symbol, control.option.depend); if (file_symbol) field_access -> symbol = ReadType(file_symbol, package, name_symbol, field_access -> identifier_token); else { PackageSymbol *subpackage = package -> FindPackageSymbol(name_symbol); if (! subpackage) subpackage = package -> InsertPackageSymbol(name_symbol); control.FindPathsToDirectory(subpackage); field_access -> symbol = subpackage; } } } } else { AstSimpleName *simple_name = name -> SimpleNameCast(); assert(simple_name); simple_name -> symbol = ProcessPackageOrType(simple_name); name_expression = simple_name; } return name_expression; } TypeSymbol *Semantic::FindSimpleNameType(PackageSymbol *package, LexStream::TokenIndex identifier_token) { NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(identifier_token); TypeSymbol *type = package -> FindTypeSymbol(name_symbol); if (type) { if (type -> SourcePending()) control.ProcessHeaders(type -> file_symbol); } else { // // Check whether or not the type was declared in another compilation unit // in the main package. // FileSymbol *file_symbol = Control::GetFile(package, name_symbol, control.option.depend); if (file_symbol) type = ReadType(file_symbol, package, name_symbol, identifier_token); } return type; } void Semantic::ProcessSingleTypeImportDeclaration(AstImportDeclaration *import_declaration) { Symbol *symbol = ProcessImportQualifiedName(import_declaration -> name); *package = symbol -> PackageCast(); if (package) { ReportSemError(SemanticError::UNKNOWN_QUALIFIED_NAME_BASE, import_declaration -> name -> LeftToken(), import_declaration -> name -> RightToken(), package -> PackageName()); return; } TypeSymbol *type = symbol -> TypeCast(); // // If two single-type-import declarations in the same compilation unit attempt to // import types with the same simple name, then a compile-time error occurs, unless // the two types are the same type, in which case the duplicate declaration is ignored. // for (int i = 0; i < single_type_imports.Length(); i++) { if (type == single_type_imports[i]) return; } TypeSymbol *old_type; int k; for (k = 0; k < compilation_unit -> NumTypeDeclarations(); k++) { AstClassDeclaration *class_declaration; AstInterfaceDeclaration *interface_declaration; if (class_declaration = compilation_unit -> TypeDeclaration(k) -> ClassDeclarationCast()) { if (class_declaration -> semantic_environment) { old_type = class_declaration -> semantic_environment -> Type(); if (old_type -> Identity() == type -> Identity()) break; } } else if (interface_declaration = compilation_unit -> TypeDeclaration(k) -> InterfaceDeclarationCast()) { if (interface_declaration -> semantic_environment) { old_type = interface_declaration -> semantic_environment -> Type(); if (old_type -> Identity() == type -> Identity()) break; } } } if (k < compilation_unit -> NumTypeDeclarations()) { ReportSemError(SemanticError::DUPLICATE_TYPE_DECLARATION, import_declaration -> name -> LeftToken(), import_declaration -> name -> RightToken(), lex_stream -> Name(import_declaration -> name -> RightToken()), old_type -> FileLoc()); } else { int i = 0; for (i = 0; i < compilation_unit -> NumImportDeclarations(); i++) { TypeSymbol *other_type = compilation_unit -> ImportDeclaration(i) -> name -> Type(); if ((compilation_unit -> ImportDeclaration(i) == import_declaration) || (other_type && other_type -> Identity() == type -> Identity())) break; } assert(i < compilation_unit -> NumImportDeclarations()); if (compilation_unit -> ImportDeclaration(i) == import_declaration) // No duplicate found { import_declaration -> name -> symbol = type; single_type_imports.Next() = type; } else { FileLocation file_location(lex_stream, compilation_unit -> ImportDeclaration(i) -> LeftToken()); ReportSemError(SemanticError::DUPLICATE_TYPE_DECLARATION, import_declaration -> name -> LeftToken(), import_declaration -> name -> RightToken(), lex_stream -> Name(import_declaration -> name -> RightToken()), file_location.location); } } if (! (type -> ACC_PUBLIC() || type -> ContainingPackage() == this_package)) ReportTypeInaccessible(import_declaration -> name, type); return; } void Semantic::ProcessFieldDeclaration(AstFieldDeclaration *field_declaration) { TypeSymbol *this_type = ThisType(); AccessFlags access_flags = (this_type -> ACC_INTERFACE() ? ProcessConstantModifiers(field_declaration) : ProcessFieldModifiers(field_declaration)); // // New feature in java 1.2 that is undocumented in the 1.1 document. // A field may be declared static iff it is final and not blank-final... // if (access_flags.ACC_STATIC() && (! access_flags.ACC_FINAL()) && this_type -> IsInner()) { AstModifier *modifier = NULL; for (int i = 0; i < field_declaration -> NumVariableModifiers(); i++) { if (field_declaration -> VariableModifier(i) -> kind == Ast::STATIC) modifier = field_declaration -> VariableModifier(i); } assert(modifier); ReportSemError(SemanticError::STATIC_FIELD_IN_INNER_CLASS, modifier -> modifier_kind_token, modifier -> modifier_kind_token); } // // // AstArrayType *array_type = field_declaration -> type -> ArrayTypeCast(); Ast *actual_type = (array_type ? array_type -> type : field_declaration -> type); AstPrimitiveType *primitive_type = actual_type -> PrimitiveTypeCast(); TypeSymbol *field_type = (primitive_type ? FindPrimitiveType(primitive_type) : MustFindType(actual_type)); for (int i = 0; i < field_declaration -> NumVariableDeclarators(); i++) { AstVariableDeclarator *variable_declarator = field_declaration -> VariableDeclarator(i); AstVariableDeclaratorId *name = variable_declarator -> variable_declarator_name; NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(name -> identifier_token); if (this_type -> FindVariableSymbol(name_symbol)) { ReportSemError(SemanticError::DUPLICATE_FIELD, name -> identifier_token, name -> identifier_token, name_symbol -> Name(), this_type -> Name()); } else { VariableSymbol *variable = this_type -> InsertVariableSymbol(name_symbol); int num_dimensions = (array_type ? array_type -> NumBrackets() : 0) + name -> NumBrackets(); if (num_dimensions == 0) variable -> SetType(field_type); else variable -> SetType(field_type -> GetArrayType((Semantic *) this, num_dimensions)); variable -> SetFlags(access_flags); variable -> SetOwner(this_type); variable -> declarator = variable_declarator; variable -> MarkIncomplete(); // the declaration of a field is not complete until its initializer // (if any) has been processed. variable_declarator -> symbol = variable; } } return; } void Semantic::GenerateLocalConstructor(MethodSymbol *constructor) { TypeSymbol *local_type = constructor -> containing_type; // // Make up external name for constructor // wchar_t info[12], *str = &info[11]; *str = U_NULL; int num = local_type -> NumGeneratedConstructors(); do { *--str = (U_0 + num % 10); num /= 10; } while (num != 0); int length = 12 + (&info[11] - str); // +12 for constructor$ wchar_t *external_name = new wchar_t[length + 1]; // +1 for '\0'; wcscpy(external_name, StringConstant::US__constructor_DOLLAR); wcscat(external_name, str); constructor -> SetExternalIdentity(control.FindOrInsertName(external_name, length)); // Turn the constructor into a method delete [] external_name; // // Make generated constructor symbol. The associated symbol table will not contain too many elements. // BlockSymbol *block_symbol = new BlockSymbol(local_type -> NumConstructorParameters() + constructor -> NumFormalParameters() + 3); block_symbol -> max_variable_index = 1; // All types need a spot for "this" MethodSymbol *local_constructor = local_type -> LocalConstructorOverload(constructor); local_constructor -> method_or_constructor_declaration = constructor -> method_or_constructor_declaration; local_constructor -> SetType(control.void_type); local_constructor -> SetContainingType(local_type); local_constructor -> SetBlockSymbol(block_symbol); ((AccessFlags *) local_constructor) -> access_flags = ((AccessFlags *) constructor) -> access_flags; for (int i = 0; i < constructor -> NumThrows(); i++) local_constructor -> AddThrows(constructor -> Throws(i)); for (int j = 0; j < local_type -> NumConstructorParameters(); j++) { VariableSymbol *param = local_type -> ConstructorParameter(j), *symbol = block_symbol -> InsertVariableSymbol(param -> Identity()); symbol -> SetType(param -> Type()); symbol -> SetOwner(local_constructor); symbol -> SetExternalIdentity(param -> ExternalIdentity()); symbol -> SetLocalVariableIndex(block_symbol -> max_variable_index++); if (symbol -> Type() == control.long_type || symbol -> Type() == control.double_type) block_symbol -> max_variable_index++; local_constructor -> AddFormalParameter(symbol); } // // Add all the parameters from the original constructor to the symbol // table of the local constructor. However, only mark them complete and // do not yet assign a number to them. This will be done after we know // how many extra "local" variable shadows are needed. // for (int k = 0; k < constructor -> NumFormalParameters(); k++) { VariableSymbol *param = constructor -> FormalParameter(k), *symbol = block_symbol -> InsertVariableSymbol(param -> Identity()); symbol -> SetType(param -> Type()); symbol -> SetOwner(local_constructor); symbol -> MarkComplete(); } local_type -> AddGeneratedConstructor(local_constructor); return; } void Semantic::ProcessConstructorDeclaration(AstConstructorDeclaration *constructor_declaration) { TypeSymbol *this_type = ThisType(); if (this_type -> Anonymous()) { ReportSemError(SemanticError::CONSTRUCTOR_FOUND_IN_ANONYMOUS_CLASS, constructor_declaration -> LeftToken(), constructor_declaration -> RightToken()); return; } AccessFlags access_flags = ProcessConstructorModifiers(constructor_declaration); AstMethodDeclarator *constructor_declarator = constructor_declaration -> constructor_declarator; NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(constructor_declarator -> identifier_token); wchar_t *constructor_name = lex_stream -> Name(constructor_declarator -> identifier_token); if (lex_stream -> NameSymbol(constructor_declarator -> identifier_token) != this_type -> Identity()) { ReportSemError(SemanticError::MISMATCHED_CONSTRUCTOR_NAME, constructor_declarator -> identifier_token, constructor_declarator -> identifier_token, constructor_name, this_type -> Name()); constructor_name = this_type -> Name(); // assume the proper name ! } // // As the body of the constructor may not have been parsed yet, we estimate a size // for its symbol table based on the number of lines in the body + a margin for one-liners. // AstConstructorBlock *block = constructor_declaration -> constructor_body -> ConstructorBlockCast(); BlockSymbol *block_symbol = new BlockSymbol(constructor_declarator -> NumFormalParameters() + 3); block_symbol -> max_variable_index = 1; // All types need a spot for "this". ProcessFormalParameters(block_symbol, constructor_declarator); // // Note that constructors are always named "<init>" // MethodSymbol *constructor = this_type -> FindMethodSymbol(control.init_name_symbol); if (! constructor) // there exists a constructor already in type -> table. constructor = this_type -> InsertConstructorSymbol(control.init_name_symbol); else { if (this_type -> FindOverloadMethod(constructor, constructor_declarator)) { ReportSemError(SemanticError::DUPLICATE_CONSTRUCTOR, constructor_declarator -> LeftToken(), constructor_declarator -> RightToken(), this_type -> Name()); delete block_symbol; return; } constructor = this_type -> Overload(constructor); } // // If the method is not static, leave a slot for the "this" pointer. // constructor -> SetType(control.void_type); constructor -> SetFlags(access_flags); constructor -> SetContainingType(this_type); constructor -> SetBlockSymbol(block_symbol); constructor -> method_or_constructor_declaration = constructor_declaration; VariableSymbol *this0_variable = NULL; if (this_type -> IsInner()) { this0_variable = block_symbol -> InsertVariableSymbol(control.this0_name_symbol); this0_variable -> SetType(this_type -> ContainingType()); this0_variable -> SetOwner(constructor); this0_variable -> SetLocalVariableIndex(block_symbol -> max_variable_index++); } for (int i = 0; i < constructor_declarator -> NumFormalParameters(); i++) { AstFormalParameter *parameter = constructor_declarator -> FormalParameter(i); VariableSymbol *symbol = parameter -> parameter_symbol; symbol -> SetOwner(constructor); symbol -> SetLocalVariableIndex(block_symbol -> max_variable_index++); if (symbol -> Type() == control.long_type || symbol -> Type() == control.double_type) block_symbol -> max_variable_index++; symbol -> declarator = parameter -> variable_declarator_name; constructor -> AddFormalParameter(symbol); } constructor -> SetSignature(control, this0_variable); for (int k = 0; k < constructor_declaration -> NumThrows(); k++) { AstExpression *throw_expression = constructor_declaration -> Throw(k); TypeSymbol *throw_type = MustFindType(throw_expression); throw_expression -> symbol = throw_type; constructor -> AddThrows(throw_type); } constructor_declaration -> constructor_symbol = constructor; // save for processing bodies later. if (this_type -> IsLocal()) GenerateLocalConstructor(constructor); return; } void Semantic::AddDefaultConstructor(TypeSymbol *type) { MethodSymbol *constructor = type -> InsertConstructorSymbol(control.init_name_symbol); BlockSymbol *block_symbol = new BlockSymbol(1); // TODO: make sure this size is right !!! block_symbol -> max_variable_index = 1; // All types need a spot for "this" constructor -> SetType(control.void_type); constructor -> SetContainingType(type); constructor -> SetBlockSymbol(block_symbol); if (type -> ACC_PUBLIC()) constructor -> SetACC_PUBLIC(); VariableSymbol *this0_variable = NULL; if (type -> IsInner()) { this0_variable = block_symbol -> InsertVariableSymbol(control.this0_name_symbol); this0_variable -> SetType(type -> ContainingType()); this0_variable -> SetOwner(constructor); this0_variable -> SetLocalVariableIndex(block_symbol -> max_variable_index++); } constructor -> SetSignature(control, this0_variable); AstClassDeclaration *class_declaration = (type -> declaration ? type -> declaration -> ClassDeclarationCast() : (AstClassDeclaration *) NULL); if (class_declaration) { AstClassBody *class_body = class_declaration -> class_body; LexStream::TokenIndex left_loc = class_declaration -> identifier_token, right_loc = (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken() : class_declaration -> identifier_token); AstMethodDeclarator *method_declarator = compilation_unit -> ast_pool -> GenMethodDeclarator(); method_declarator -> identifier_token = left_loc; method_declarator -> left_parenthesis_token = left_loc; method_declarator -> right_parenthesis_token = right_loc; AstSuperCall *super_call = NULL; if (type != control.Object()) { super_call = compilation_unit -> ast_pool -> GenSuperCall(); super_call -> base_opt = NULL; super_call -> dot_token_opt = left_loc; super_call -> super_token = left_loc; super_call -> left_parenthesis_token = left_loc; super_call -> right_parenthesis_token = right_loc; super_call -> semicolon_token = right_loc; } AstReturnStatement *return_statement = compilation_unit -> ast_pool -> GenReturnStatement(); return_statement -> return_token = left_loc; return_statement -> expression_opt = NULL; return_statement -> semicolon_token = left_loc; return_statement -> is_reachable = true; AstBlock *block = compilation_unit -> ast_pool -> GenBlock(); block -> AllocateBlockStatements(1); // this block contains one statement block -> left_brace_token = left_loc; block -> right_brace_token = right_loc; block -> is_reachable = true; block -> can_complete_normally = false; block -> AddStatement(return_statement); AstConstructorBlock *constructor_block = compilation_unit -> ast_pool -> GenConstructorBlock(); constructor_block -> left_brace_token = left_loc; constructor_block -> explicit_constructor_invocation_opt = super_call; constructor_block -> block = block; constructor_block -> right_brace_token = right_loc; AstConstructorDeclaration *constructor_declaration = compilation_unit -> ast_pool -> GenConstructorDeclaration(); constructor_declaration -> constructor_declarator = method_declarator; constructor_declaration -> constructor_body = constructor_block; constructor_declaration -> constructor_symbol = constructor; constructor -> method_or_constructor_declaration = constructor_declaration; class_body -> default_constructor = constructor_declaration; if (type -> IsLocal()) GenerateLocalConstructor(constructor); } return; } void Semantic::CheckInheritedMethodThrows(AstMethodDeclaration *method_declaration, MethodSymbol *method) { for (int i = 0; i < method_declaration -> NumThrows(); i++) { AstExpression *name = method_declaration -> Throw(i); TypeSymbol *exception = (TypeSymbol *) name -> symbol; if (CheckedException(exception)) { int k; for (k = method -> NumThrows((Semantic *) this, name -> RightToken()) - 1; k >= 0; k--) { if (exception -> IsSubclass(method -> Throws(k))) break; } if (k < 0) { ReportSemError(SemanticError::MISMATCHED_OVERRIDDEN_EXCEPTION, name -> LeftToken(), name -> RightToken(), exception -> Name(), method -> Header((Semantic *) this, name -> RightToken()), method -> containing_type -> ContainingPackage() -> PackageName(), method -> containing_type -> ExternalName()); } } } return; } void Semantic::CheckMethodOverride(AstMethodDeclaration *method_declaration, MethodSymbol *hidden_method) { AstMethodDeclarator *method_declarator = method_declaration -> method_declarator; MethodSymbol *method = method_declaration -> method_symbol; LexStream::TokenIndex token_location = method_declaration -> method_declarator -> identifier_token; if (hidden_method -> Type() != method -> Type()) ReportSemError(SemanticError::MISMATCHED_INHERITED_METHOD, method_declarator -> LeftToken(), method_declarator -> RightToken(), method -> Header((Semantic *) this, token_location), hidden_method -> Header((Semantic *) this, token_location), hidden_method -> containing_type -> ContainingPackage() -> PackageName(), hidden_method -> containing_type -> ExternalName()); if (hidden_method -> IsFinal() || hidden_method -> ACC_PRIVATE()) // Merged because same kind of message. See error.cpp ReportSemError(hidden_method -> IsFinal() ? SemanticError::FINAL_METHOD_OVERRIDE : SemanticError::PRIVATE_METHOD_OVERRIDE, method_declarator -> LeftToken(), method_declarator -> RightToken(), method -> Header((Semantic *) this, token_location), hidden_method -> Header((Semantic *) this, token_location), hidden_method -> containing_type -> ContainingPackage() -> PackageName(), hidden_method -> containing_type -> ExternalName()); if (method -> ACC_STATIC() != hidden_method -> ACC_STATIC()) { if (method -> ACC_STATIC()) ReportSemError(SemanticError::INSTANCE_METHOD_OVERRIDE, method_declarator -> LeftToken(), method_declarator -> RightToken(), method -> Header((Semantic *) this, token_location), hidden_method -> Header((Semantic *) this, token_location), hidden_method -> containing_type -> ContainingPackage() -> PackageName(), hidden_method -> containing_type -> ExternalName()); else ReportSemError(SemanticError::CLASS_METHOD_OVERRIDE, method_declarator -> LeftToken(), method_declarator -> RightToken(), method -> Header((Semantic *) this, token_location), hidden_method -> Header((Semantic *) this, token_location), hidden_method -> containing_type -> ContainingPackage() -> PackageName(), hidden_method -> containing_type -> ExternalName()); } if (hidden_method -> ACC_PUBLIC()) { if (! method -> ACC_PUBLIC()) ReportSemError(SemanticError::BAD_ACCESS_METHOD_OVERRIDE, method_declarator -> LeftToken(), method_declarator -> RightToken(), method -> Header((Semantic *) this, token_location), (method -> ACC_PRIVATE() ? StringConstant::US_private : (method -> ACC_PROTECTED() ? StringConstant::US_protected : StringConstant::US_default)), hidden_method -> Header((Semantic *) this, token_location), StringConstant::US_public, hidden_method -> containing_type -> ContainingPackage() -> PackageName(), hidden_method -> containing_type -> ExternalName()); } else if (hidden_method -> ACC_PROTECTED()) { if (! (method -> ACC_PROTECTED() || method -> ACC_PUBLIC())) ReportSemError(SemanticError::BAD_ACCESS_METHOD_OVERRIDE, method_declarator -> LeftToken(), method_declarator -> RightToken(), method -> Header((Semantic *) this, token_location), StringConstant::US_default, hidden_method -> Header((Semantic *) this, token_location), StringConstant::US_protected, hidden_method -> containing_type -> ContainingPackage() -> PackageName(), hidden_method -> containing_type -> ExternalName()); } else if (method -> ACC_PRIVATE()) // The hidden_method method must have default access as it cannot be private... { ReportSemError(SemanticError::BAD_ACCESS_METHOD_OVERRIDE, method_declarator -> LeftToken(), method_declarator -> RightToken(), method -> Header((Semantic *) this, token_location), StringConstant::US_private, hidden_method -> Header((Semantic *) this, token_location), StringConstant::US_default, hidden_method -> containing_type -> ContainingPackage() -> PackageName(), hidden_method -> containing_type -> ExternalName()); } CheckInheritedMethodThrows(method_declaration, hidden_method); return; } void Semantic::CheckInheritedMethodThrows(AstClassDeclaration *class_declaration, MethodSymbol *method, MethodSymbol *hidden_method) { for (int i = method -> NumThrows((Semantic *) this, class_declaration -> identifier_token) - 1; i >= 0; i--) { TypeSymbol *exception = method -> Throws(i); if (CheckedException(exception)) { int k; for (k = hidden_method -> NumThrows((Semantic *) this, class_declaration -> identifier_token) - 1; k >= 0; k--) { if (exception -> IsSubclass(hidden_method -> Throws(k))) break; } if (k < 0) { ReportSemError(SemanticError::MISMATCHED_OVERRIDDEN_EXCEPTION_EXTERNALLY, class_declaration -> identifier_token, (class_declaration -> NumInterfaces() > 0 ? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken() : (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken() : class_declaration -> identifier_token)), lex_stream -> Name(class_declaration -> identifier_token), exception -> Name(), method -> Header((Semantic *) this, class_declaration -> identifier_token), hidden_method -> containing_type -> ContainingPackage() -> PackageName(), hidden_method -> containing_type -> ExternalName(), hidden_method -> Header((Semantic *) this, class_declaration -> identifier_token), method -> containing_type -> ContainingPackage() -> PackageName(), method -> containing_type -> ExternalName()); } } } return; } void Semantic::CheckMethodOverride(AstClassDeclaration *class_declaration, MethodSymbol *method, MethodSymbol *hidden_method) { if (hidden_method -> Type() != method -> Type()) ReportSemError(SemanticError::MISMATCHED_INHERITED_METHOD_EXTERNALLY, class_declaration -> identifier_token, (class_declaration -> NumInterfaces() > 0 ? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken() : (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken() : class_declaration -> identifier_token)), lex_stream -> Name(class_declaration -> identifier_token), method -> Header((Semantic *) this, class_declaration -> identifier_token), method -> containing_type -> ContainingPackage() -> PackageName(), method -> containing_type -> ExternalName(), hidden_method -> Header((Semantic *) this, class_declaration -> identifier_token), hidden_method -> containing_type -> ContainingPackage() -> PackageName(), hidden_method -> containing_type -> ExternalName()); if (hidden_method -> IsFinal() || hidden_method -> ACC_PRIVATE()) // Merged because same kind of message. See error.cpp ReportSemError(hidden_method -> IsFinal() ? SemanticError::FINAL_METHOD_OVERRIDE_EXTERNALLY : SemanticError::PRIVATE_METHOD_OVERRIDE_EXTERNALLY, class_declaration -> identifier_token, (class_declaration -> NumInterfaces() > 0 ? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken() : (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken() : class_declaration -> identifier_token)), lex_stream -> Name(class_declaration -> identifier_token), method -> Header((Semantic *) this, class_declaration -> identifier_token), method -> containing_type -> ContainingPackage() -> PackageName(), method -> containing_type -> ExternalName(), hidden_method -> Header((Semantic *) this, class_declaration -> identifier_token), hidden_method -> containing_type -> ContainingPackage() -> PackageName(), hidden_method -> containing_type -> ExternalName()); if (method -> ACC_STATIC() != hidden_method -> ACC_STATIC()) { if (method -> ACC_STATIC()) ReportSemError(SemanticError::INSTANCE_METHOD_OVERRIDE_EXTERNALLY, class_declaration -> identifier_token, (class_declaration -> NumInterfaces() > 0 ? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken() : (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken() : class_declaration -> identifier_token)), lex_stream -> Name(class_declaration -> identifier_token), method -> Header((Semantic *) this, class_declaration -> identifier_token), method -> containing_type -> ContainingPackage() -> PackageName(), method -> containing_type -> ExternalName(), hidden_method -> Header((Semantic *) this, class_declaration -> identifier_token), hidden_method -> containing_type -> ContainingPackage() -> PackageName(), hidden_method -> containing_type -> ExternalName()); else ReportSemError(SemanticError::CLASS_METHOD_OVERRIDE_EXTERNALLY, class_declaration -> identifier_token, (class_declaration -> NumInterfaces() > 0 ? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken() : (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken() : class_declaration -> identifier_token)), lex_stream -> Name(class_declaration -> identifier_token), method -> Header((Semantic *) this, class_declaration -> identifier_token), method -> containing_type -> ContainingPackage() -> PackageName(), method -> containing_type -> ExternalName(), hidden_method -> Header((Semantic *) this, class_declaration -> identifier_token), hidden_method -> containing_type -> ContainingPackage() -> PackageName(), hidden_method -> containing_type -> ExternalName()); } if (hidden_method -> ACC_PUBLIC()) { if (! method -> ACC_PUBLIC()) ReportSemError(SemanticError::BAD_ACCESS_METHOD_OVERRIDE_EXTERNALLY, class_declaration -> identifier_token, (class_declaration -> NumInterfaces() > 0 ? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken() : (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken() : class_declaration -> identifier_token)), lex_stream -> Name(class_declaration -> identifier_token), method -> Header((Semantic *) this, class_declaration -> identifier_token), (method -> ACC_PRIVATE() ? StringConstant::US_private : (method -> ACC_PROTECTED() ? StringConstant::US_protected : StringConstant::US_default)), method -> containing_type -> ContainingPackage() -> PackageName(), method -> containing_type -> ExternalName(), hidden_method -> Header((Semantic *) this, class_declaration -> identifier_token), StringConstant::US_public, hidden_method -> containing_type -> ContainingPackage() -> PackageName(), hidden_method -> containing_type -> ExternalName()); } else if (hidden_method -> ACC_PROTECTED()) { if (! (method -> ACC_PROTECTED() || method -> ACC_PUBLIC())) ReportSemError(SemanticError::BAD_ACCESS_METHOD_OVERRIDE, class_declaration -> identifier_token, (class_declaration -> NumInterfaces() > 0 ? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken() : (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken() : class_declaration -> identifier_token)), lex_stream -> Name(class_declaration -> identifier_token), method -> Header((Semantic *) this, class_declaration -> identifier_token), StringConstant::US_default, method -> containing_type -> ContainingPackage() -> PackageName(), method -> containing_type -> ExternalName(), hidden_method -> Header((Semantic *) this, class_declaration -> identifier_token), StringConstant::US_protected, hidden_method -> containing_type -> ContainingPackage() -> PackageName(), hidden_method -> containing_type -> ExternalName()); } else if (method -> ACC_PRIVATE()) // The hidden_method method must have default access as it cannot be private... { ReportSemError(SemanticError::BAD_ACCESS_METHOD_OVERRIDE_EXTERNALLY, class_declaration -> identifier_token, (class_declaration -> NumInterfaces() > 0 ? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken() : (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken() : class_declaration -> identifier_token)), lex_stream -> Name(class_declaration -> identifier_token), method -> Header((Semantic *) this, class_declaration -> identifier_token), StringConstant::US_private, method -> containing_type -> ContainingPackage() -> PackageName(), method -> containing_type -> ExternalName(), hidden_method -> Header((Semantic *) this, class_declaration -> identifier_token), StringConstant::US_default, hidden_method -> containing_type -> ContainingPackage() -> PackageName(), hidden_method -> containing_type -> ExternalName()); } CheckInheritedMethodThrows(class_declaration, method, hidden_method); return; } void Semantic::AddInheritedTypes(TypeSymbol *base_type, TypeSymbol *super_type) { ExpandedTypeTable &base_expanded_table = *(base_type -> expanded_type_table), &super_expanded_table = *(super_type -> expanded_type_table); for (int j = 0; j < super_expanded_table.symbol_pool.Length(); j++) { TypeShadowSymbol *type_shadow_symbol = super_expanded_table.symbol_pool[j]; TypeSymbol *type_symbol = type_shadow_symbol -> type_symbol; // // Note that since all fields in an interface are implicitly public, all other fields // encountered here are enclosed in a type that is a super class of base_type. // if (type_symbol -> ACC_PUBLIC() || type_symbol -> ACC_PROTECTED() || ((! type_symbol -> ACC_PRIVATE()) && (super_type -> ContainingPackage() == base_type -> ContainingPackage()))) { NameSymbol *name_symbol = type_symbol -> Identity(); TypeShadowSymbol *shadow = base_expanded_table.FindTypeShadowSymbol(name_symbol); if (! shadow) base_expanded_table.InsertTypeShadowSymbol(type_symbol); else if (shadow -> type_symbol -> owner != base_type) { shadow -> AddConflict(type_symbol); if (type_symbol -> owner != super_type) // main type doesn't override all other fields? process conflicts. { for (int k = 0; k < type_shadow_symbol -> NumConflicts(); k++) shadow -> AddConflict(type_shadow_symbol -> Conflict(k)); } } // // TODO: maybe? if base_type is a nested type check if a type with the same // name appears in one of the enclosed lexical scopes. If so, add // it to the shadow! // } } return; } void Semantic::AddInheritedFields(TypeSymbol *base_type, TypeSymbol *super_type) { ExpandedFieldTable &base_expanded_table = *(base_type -> expanded_field_table), &super_expanded_table = *(super_type -> expanded_field_table); for (int i = 0; i < super_expanded_table.symbol_pool.Length(); i++) { VariableShadowSymbol *variable_shadow_symbol = super_expanded_table.symbol_pool[i]; VariableSymbol *variable_symbol = variable_shadow_symbol -> variable_symbol; // // Note that since all fields in an interface are implicitly public, all other fields // encountered here are enclosed in a type that is a super class of base_type. // if (variable_symbol -> ACC_PUBLIC() || variable_symbol -> ACC_PROTECTED() || ((! variable_symbol -> ACC_PRIVATE()) && (super_type -> ContainingPackage() == base_type -> ContainingPackage()))) { NameSymbol *name_symbol = variable_symbol -> Identity(); VariableShadowSymbol *shadow = base_expanded_table.FindVariableShadowSymbol(name_symbol); if (! shadow) base_expanded_table.InsertVariableShadowSymbol(variable_symbol); else if (shadow -> variable_symbol -> owner != base_type) { shadow -> AddConflict(variable_symbol); if (variable_symbol -> owner != super_type) // main variable doesn't override all other fields? process conflicts. { for (int k = 0; k < variable_shadow_symbol -> NumConflicts(); k++) shadow -> AddConflict(variable_shadow_symbol -> Conflict(k)); } } } } return; } void Semantic::AddInheritedMethods(TypeSymbol *base_type, TypeSymbol *super_type, LexStream::TokenIndex tok) { ExpandedMethodTable &base_expanded_table = *(base_type -> expanded_method_table), &super_expanded_table = *(super_type -> expanded_method_table); for (int k = 0; k < super_expanded_table.symbol_pool.Length(); k++) { MethodShadowSymbol *method_shadow_symbol = super_expanded_table.symbol_pool[k]; MethodSymbol *method = method_shadow_symbol -> method_symbol; // // Note that since all fields in an interface are implicitly // public, all other fields encountered here are enclosed in a // type that is a super class of base_type. // if (method -> ACC_PUBLIC() || method -> ACC_PROTECTED() || ((! method -> ACC_PRIVATE()) && (super_type -> ContainingPackage() == base_type -> ContainingPackage()))) { MethodShadowSymbol *base_method_shadow = base_expanded_table.FindMethodShadowSymbol(method -> Identity()); if (! base_method_shadow) base_expanded_table.InsertMethodShadowSymbol(method); else { MethodShadowSymbol *shadow = base_expanded_table.FindOverloadMethodShadow(method, (Semantic *) this, tok); if (! shadow) base_expanded_table.Overload(base_method_shadow, method); else { shadow -> AddConflict(method); // // If main method in question does not override all other methods, // add all other conflicting methods. // if (method -> containing_type != super_type) { for (int i = 0; i < method_shadow_symbol -> NumConflicts(); i++) shadow -> AddConflict(method_shadow_symbol -> Conflict(i)); } } } } else if (! (method -> ACC_PRIVATE() || method -> IsSynthetic())) // Not amethod with default access from another package? { MethodShadowSymbol *base_method_shadow = base_expanded_table.FindMethodShadowSymbol(method -> Identity()); if (base_method_shadow) { MethodShadowSymbol *shadow = base_expanded_table.FindOverloadMethodShadow(method, (Semantic *) this, tok); if (shadow) { LexStream::TokenIndex left_tok, right_tok; if (ThisType() == base_type) { AstMethodDeclaration *method_declaration = (AstMethodDeclaration *) shadow -> method_symbol -> method_or_constructor_declaration; AstMethodDeclarator *method_declarator = method_declaration -> method_declarator; left_tok = method_declarator -> LeftToken(); right_tok = method_declarator -> RightToken(); } else { AstInterfaceDeclaration *interface_declaration = ThisType() -> declaration -> InterfaceDeclarationCast(); AstClassDeclaration *class_declaration = ThisType() -> declaration -> ClassDeclarationCast(); if (interface_declaration) { left_tok = right_tok = interface_declaration -> identifier_token; } else if (class_declaration) { left_tok = right_tok = class_declaration -> identifier_token; } else { AstClassInstanceCreationExpression *class_creation = ThisType() -> declaration -> ClassInstanceCreationExpressionCast(); assert(class_creation); left_tok = class_creation -> class_type -> LeftToken(); right_tok = class_creation -> class_type -> RightToken(); } } ReportSemError(SemanticError::DEFAULT_METHOD_NOT_OVERRIDDEN, left_tok, right_tok, method -> Header((Semantic *) this, tok), base_type -> ContainingPackage() -> PackageName(), base_type -> ExternalName(), super_type -> ContainingPackage() -> PackageName(), super_type -> ExternalName()); } } } } return; } void Semantic::ComputeTypesClosure(TypeSymbol *type, LexStream::TokenIndex tok) { type -> expanded_type_table = new ExpandedTypeTable(); TypeSymbol *super_class = type -> super; if (super_class) { if (! super_class -> expanded_type_table) ComputeTypesClosure(super_class, tok); } for (int j = 0; j < type -> NumInterfaces(); j++) { TypeSymbol *interf = type -> Interface(j); if (! interf -> expanded_type_table) ComputeTypesClosure(interf, tok); } if (! type -> NestedTypesProcessed()) type -> ProcessNestedTypeSignatures((Semantic *) this, tok); for (int i = 0; i < type -> NumTypeSymbols(); i++) { if (! type -> TypeSym(i) -> Bad()) type -> expanded_type_table -> InsertTypeShadowSymbol(type -> TypeSym(i)); } if (super_class) AddInheritedTypes(type, super_class); for (int k = 0; k < type -> NumInterfaces(); k++) AddInheritedTypes(type, type -> Interface(k)); type -> expanded_type_table -> CompressSpace(); return; } void Semantic::ComputeFieldsClosure(TypeSymbol *type, LexStream::TokenIndex tok) { type -> expanded_field_table = new ExpandedFieldTable(); TypeSymbol *super_class = type -> super; if (super_class) { if (! super_class -> expanded_field_table) ComputeFieldsClosure(super_class, tok); } for (int j = 0; j < type -> NumInterfaces(); j++) { TypeSymbol *interf = type -> Interface(j); if (! interf -> expanded_field_table) ComputeFieldsClosure(interf, tok); } assert(type -> FieldMembersProcessed()); for (int i = 0; i < type -> NumVariableSymbols(); i++) { VariableSymbol *variable = type -> VariableSym(i); type -> expanded_field_table -> InsertVariableShadowSymbol(variable); } // // As the type Object which is the super type of all interfaces does // not contain any field declarations, we don't have to do any special // check here as we have to when computing method closures. // if (super_class) AddInheritedFields(type, super_class); for (int k = 0; k < type -> NumInterfaces(); k++) AddInheritedFields(type, type -> Interface(k)); type -> expanded_field_table -> CompressSpace(); return; } void Semantic::ComputeMethodsClosure(TypeSymbol *type, LexStream::TokenIndex tok) { type -> expanded_method_table = new ExpandedMethodTable(); TypeSymbol *super_class = type -> super; if (super_class) { if (! super_class -> expanded_method_table) ComputeMethodsClosure(super_class, tok); } for (int j = 0; j < type -> NumInterfaces(); j++) { TypeSymbol *interf = type -> Interface(j); if (! interf -> expanded_method_table) ComputeMethodsClosure(interf, tok); } assert(type -> MethodMembersProcessed()); for (int i = 0; i < type -> NumMethodSymbols(); i++) { MethodSymbol *method = type -> MethodSym(i); // // If the method in question is neither a constructor nor an // initializer, then ... // if (method -> Identity() != control.init_name_symbol && // method -> Identity() != control.block_init_name_symbol && // method -> Identity() != control.clinit_name_symbol) // if (*(method -> Name()) != U_LESS) { type -> expanded_method_table -> Overload(method); } } if (super_class && (! type -> ACC_INTERFACE())) AddInheritedMethods(type, super_class, tok); for (int k = 0; k < type -> NumInterfaces(); k++) AddInheritedMethods(type, type -> Interface(k), tok); if (type -> ACC_INTERFACE()) // the super class is Object AddInheritedMethods(type, control.Object(), tok); type -> expanded_method_table -> CompressSpace(); return; } void Semantic::ProcessFormalParameters(BlockSymbol *block, AstMethodDeclarator *method_declarator) { for (int i = 0; i < method_declarator -> NumFormalParameters(); i++) { AstFormalParameter *parameter = method_declarator -> FormalParameter(i); AstArrayType *array_type = parameter -> type -> ArrayTypeCast(); Ast *actual_type = (array_type ? array_type -> type : parameter -> type); if ((! control.option.one_one) && parameter -> NumParameterModifiers() > 0) { ReportSemError(SemanticError::ONE_ONE_FEATURE, parameter -> ParameterModifier(0) -> LeftToken(), parameter -> ParameterModifier(0) -> RightToken()); } AccessFlags access_flags = ProcessFormalModifiers(parameter); AstPrimitiveType *primitive_type = actual_type -> PrimitiveTypeCast(); TypeSymbol *parm_type = (primitive_type ? FindPrimitiveType(primitive_type) : MustFindType(actual_type)); AstVariableDeclaratorId *name = parameter -> variable_declarator_name; NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(name -> identifier_token); VariableSymbol *symbol = block -> FindVariableSymbol(name_symbol); if (symbol) { ReportSemError(SemanticError::DUPLICATE_FORMAL_PARAMETER, name -> identifier_token, name -> identifier_token, name_symbol -> Name()); } else symbol = block -> InsertVariableSymbol(name_symbol); int num_dimensions = (array_type ? array_type -> NumBrackets() : 0) + name -> NumBrackets(); if (num_dimensions == 0) symbol -> SetType(parm_type); else symbol -> SetType(parm_type -> GetArrayType((Semantic *) this, num_dimensions)); symbol -> SetFlags(access_flags); symbol -> MarkComplete(); parameter -> parameter_symbol = symbol; } return; } void Semantic::ProcessMethodDeclaration(AstMethodDeclaration *method_declaration) { TypeSymbol *this_type = ThisType(); AccessFlags access_flags = (this_type -> ACC_INTERFACE() ? ProcessAbstractMethodModifiers(method_declaration) : ProcessMethodModifiers(method_declaration)); // // TODO: File Query Sun on that one. We no longer explicitly mark such methods as final // as it appears that some tools expect these methods to remain unmarked. // // // A private method and all methods declared in a final class are implicitly final. // // if (access_flags.ACC_PRIVATE() || this_type -> ACC_FINAL()) // access_flags.SetACC_FINAL(); // // // A method enclosed in an inner type may not be declared static. // if (access_flags.ACC_STATIC() && this_type -> IsInner()) { AstModifier *modifier = NULL; for (int i = 0; i < method_declaration -> NumMethodModifiers(); i++) { if (method_declaration -> MethodModifier(i) -> kind == Ast::STATIC) modifier = method_declaration -> MethodModifier(i); } assert(modifier); ReportSemError(SemanticError::STATIC_METHOD_IN_INNER_CLASS, modifier -> modifier_kind_token, modifier -> modifier_kind_token); } // // // AstArrayType *array_type = method_declaration -> type -> ArrayTypeCast(); Ast *actual_type = (array_type ? array_type -> type : method_declaration -> type); AstPrimitiveType *primitive_type = actual_type -> PrimitiveTypeCast(); TypeSymbol *method_type = (primitive_type ? FindPrimitiveType(primitive_type) : MustFindType(actual_type)); AstMethodDeclarator *method_declarator = method_declaration -> method_declarator; if (method_declarator -> NumBrackets() > 0) { if (method_type == control.void_type) ReportSemError(SemanticError::VOID_ARRAY, method_declaration -> type -> LeftToken(), method_declarator -> RightToken()); else ReportSemError(SemanticError::OBSOLESCENT_BRACKETS, method_declarator -> LeftToken(), method_declarator -> RightToken()); } NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(method_declarator -> identifier_token); if (name_symbol == this_type -> Identity()) { ReportSemError(SemanticError::METHOD_WITH_CONSTRUCTOR_NAME, method_declaration -> type -> LeftToken(), method_declarator -> identifier_token, name_symbol -> Name()); } // // As the body of the method may not have been parsed yet, we estimate a size // for its symbol table based on the number of lines in the body + a margin for one-liners. // AstBlock *block = method_declaration -> method_body -> BlockCast(); BlockSymbol *block_symbol = new BlockSymbol(method_declarator -> NumFormalParameters()); block_symbol -> max_variable_index = (access_flags.ACC_STATIC() ? 0 : 1); ProcessFormalParameters(block_symbol, method_declarator); MethodSymbol *method = this_type -> FindMethodSymbol(name_symbol); if (! method) method = this_type -> InsertMethodSymbol(name_symbol); else { if (this_type -> FindOverloadMethod(method, method_declarator)) { ReportSemError(SemanticError::DUPLICATE_METHOD, method_declarator -> LeftToken(), method_declarator -> RightToken(), name_symbol -> Name(), this_type -> Name()); delete block_symbol; return; } method = this_type -> Overload(method); } int num_dimensions = (method_type == control.void_type ? 0 : (array_type ? array_type -> NumBrackets() : 0) + method_declarator -> NumBrackets()); if (num_dimensions == 0) method -> SetType(method_type); else method -> SetType(method_type -> GetArrayType((Semantic *) this, num_dimensions)); // // if the method is not static, leave a slot for the "this" pointer. // method -> SetFlags(access_flags); method -> SetContainingType(this_type); method -> SetBlockSymbol(block_symbol); method -> method_or_constructor_declaration = method_declaration; for (int i = 0; i < method_declarator -> NumFormalParameters(); i++) { AstFormalParameter *parameter = method_declarator -> FormalParameter(i); VariableSymbol *symbol = parameter -> parameter_symbol; symbol -> SetOwner(method); symbol -> SetLocalVariableIndex(block_symbol -> max_variable_index++); if (symbol -> Type() == control.long_type || symbol -> Type() == control.double_type) block_symbol -> max_variable_index++; symbol -> declarator = parameter -> variable_declarator_name; method -> AddFormalParameter(symbol); } method -> SetSignature(control); for (int k = 0; k < method_declaration -> NumThrows(); k++) { AstExpression *throw_expression = method_declaration -> Throw(k); TypeSymbol *throw_type = MustFindType(throw_expression); throw_expression -> symbol = throw_type; method -> AddThrows(throw_type); } method_declaration -> method_symbol = method; // save for processing bodies later. if (method -> ACC_ABSTRACT() && (! this_type -> ACC_ABSTRACT())) { ReportSemError(SemanticError::NON_ABSTRACT_TYPE_CONTAINS_ABSTRACT_METHOD, method_declaration -> LeftToken(), method_declarator -> identifier_token, name_symbol -> Name(), this_type -> Name()); } return; } // // Search for simple identifier which is supposed to be a type. // If it is not found, issue an error message. // TypeSymbol *Semantic::FindPrimitiveType(AstPrimitiveType *primitive_type) { switch(primitive_type -> kind) { case Ast::INT: return control.int_type; case Ast::DOUBLE: return control.double_type; case Ast::CHAR: return control.char_type; case Ast::LONG: return control.long_type; case Ast::FLOAT: return control.float_type; case Ast::BYTE: return control.byte_type; case Ast::SHORT: return control.short_type; case Ast::BOOLEAN: return control.boolean_type; default: break; } return control.void_type; } TypeSymbol *Semantic::ImportType(LexStream::TokenIndex identifier_token, NameSymbol *name_symbol) { TypeSymbol *type = NULL; PackageSymbol *package = NULL; FileSymbol *file_symbol = NULL; for (int i = 0; i < import_on_demand_packages.Length(); i++) { PackageSymbol *import_package = import_on_demand_packages[i] -> PackageCast(); if (import_package) { FileSymbol *symbol = Control::GetFile(import_package, name_symbol, control.option.depend); if (symbol) { if (! package) { file_symbol = symbol; package = import_package; } else { ReportSemError(SemanticError::DUPLICATE_ON_DEMAND_IMPORT, identifier_token, identifier_token, name_symbol -> Name(), package -> PackageName(), import_package -> PackageName()); } } } else { TypeSymbol *import_type = (TypeSymbol *) import_on_demand_packages[i]; if (! import_type -> expanded_type_table) ComputeTypesClosure(import_type, identifier_token); TypeShadowSymbol *type_shadow_symbol = import_type -> expanded_type_table -> FindTypeShadowSymbol(name_symbol); if (type_shadow_symbol) type = FindTypeInShadow(type_shadow_symbol, identifier_token); } } if (! type) { if (package) { type = package -> FindTypeSymbol(name_symbol); if (! type) type = ReadType(file_symbol, package, name_symbol, identifier_token); else if (type -> SourcePending()) control.ProcessHeaders(type -> file_symbol); } } if (type && (! (type -> ACC_PUBLIC() || type -> ContainingPackage() == this_package))) ReportTypeInaccessible(identifier_token, identifier_token, type); return type; } TypeSymbol *Semantic::FindType(LexStream::TokenIndex identifier_token) { TypeSymbol *type; NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(identifier_token); SemanticEnvironment *env; for (env = state_stack.Top(); env; env = env -> previous) { type = env -> symbol_table.FindTypeSymbol(name_symbol); if (type) break; type = env -> Type(); if (name_symbol == type -> Identity()) // Recall that a type may not have the same name as one of its enclosing types. break; if (! type -> expanded_type_table) ComputeTypesClosure(type, identifier_token); TypeShadowSymbol *type_shadow_symbol = type -> expanded_type_table -> FindTypeShadowSymbol(name_symbol); if (type_shadow_symbol) { type = FindTypeInShadow(type_shadow_symbol, identifier_token); break; } } if (env) // The type was found in some enclosing environment? { // // If the type is an inherited type, make sure that there is not a // type of the same name within an enclosing lexical scope. // if (type -> owner -> TypeCast() && type -> owner != env -> Type()) { for (SemanticEnvironment *env2 = env -> previous; env2; env2 = env2 -> previous) { TypeSymbol *outer_type = env2 -> symbol_table.FindTypeSymbol(name_symbol); // check local type if (! outer_type) // if local type not found, check inner type... { if (! env2 -> Type() -> expanded_type_table) ComputeTypesClosure(env2 -> Type(), identifier_token); TypeShadowSymbol *type_shadow_symbol = env2 -> Type() -> expanded_type_table -> FindTypeShadowSymbol(name_symbol); if (type_shadow_symbol) outer_type = FindTypeInShadow(type_shadow_symbol, identifier_token); } // // If a different type of the same name was found in an enclosing scope. // if (outer_type && outer_type != type) { MethodSymbol *method = outer_type -> owner -> MethodCast(); if (method) { ReportSemError(SemanticError::INHERITANCE_AND_LEXICAL_SCOPING_CONFLICT_WITH_LOCAL, identifier_token, identifier_token, lex_stream -> Name(identifier_token), env -> Type() -> ContainingPackage() -> PackageName(), env -> Type() -> ExternalName(), method -> Name()); break; } else { ReportSemError(SemanticError::INHERITANCE_AND_LEXICAL_SCOPING_CONFLICT_WITH_MEMBER, identifier_token, identifier_token, lex_stream -> Name(identifier_token), env -> Type() -> ContainingPackage() -> PackageName(), env -> Type() -> ExternalName(), env2 -> Type() -> ContainingPackage() -> PackageName(), env2 -> Type() -> ExternalName()); break; } } } } return type; } // // check whether or not the type is in the current compilation unit // either because it was declared as a class or interface or it was // imported by a single-type-import declaration. // for (int i = 0; i < single_type_imports.Length(); i++) { type = single_type_imports[i]; if (name_symbol == type -> Identity()) return type; } // // If a package was specified in this file (the one we are compiling), // we look for the type requested inside the package in question. // Otherwise, we look for the type requested in the unnamed package. // PackageSymbol *package = (compilation_unit -> package_declaration_opt ? this_package : control.unnamed_package); type = FindSimpleNameType(package, identifier_token); // // Note that a type T contained in a package P is always accessible to all other // types contained in P. I.e., we do not need to perform access check for type. // if (type) { // // If a type T was specified in a source file that is not called T.java // but X.java (where X != T) and we are not currently compiling file X, // issue a warning to alert the user that in some circumstances, this // may not be visible. (i.e., if the file X has not yet been compiled, // then T is invisile as the compiler will only look for T in T.java.) // FileSymbol *file_symbol = type -> file_symbol; if (file_symbol && (type -> Identity() != file_symbol -> Identity()) && (file_symbol != this -> source_file_symbol)) { ReportSemError(SemanticError::REFERENCE_TO_TYPE_IN_MISMATCHED_FILE, identifier_token, identifier_token, type -> Name(), file_symbol -> Name()); } return type; } // // check whether or not the type can be imported on demand from // exactly one package or type. // return ImportType(identifier_token, name_symbol); } // // // TypeSymbol *Semantic::MustFindType(Ast *name) { TypeSymbol *type; LexStream::TokenIndex identifier_token; AstSimpleName *simple_name = name -> SimpleNameCast(); if (simple_name) { identifier_token = simple_name -> identifier_token; type = FindType(identifier_token); // // If the type was not found, try to read it again to generate an appropriate error message. // if (! type) { NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(identifier_token); PackageSymbol *package = (compilation_unit -> package_declaration_opt ? this_package : control.unnamed_package); FileSymbol *file_symbol = Control::GetFile(package, name_symbol, control.option.depend); type = ReadType(file_symbol, package, name_symbol, identifier_token); } else { TypeAccessCheck(name, type); } } else { AstFieldAccess *field_access = name -> FieldAccessCast(); assert(field_access); identifier_token = field_access -> identifier_token; Symbol *symbol = ProcessPackageOrType(field_access -> base); type = symbol -> TypeCast(); if (type) { TypeNestAccessCheck(field_access -> base); type = MustFindNestedType(type, field_access); } else { PackageSymbol *package = symbol -> PackageCast(); if (package -> directory.Length() == 0) { ReportSemError(SemanticError::PACKAGE_NOT_FOUND, field_access -> base -> LeftToken(), field_access -> base -> RightToken(), package -> PackageName()); } NameSymbol *name_symbol = (NameSymbol *) lex_stream -> NameSymbol(identifier_token); type = package -> FindTypeSymbol(name_symbol); if (! type) { FileSymbol *file_symbol = Control::GetFile(package, name_symbol, control.option.depend); type = ReadType(file_symbol, package, name_symbol, identifier_token); } else { if (type -> SourcePending()) control.ProcessHeaders(type -> file_symbol); TypeAccessCheck(name, type); } } } // // Establish a dependence from base_type to a type that it "must find". // AddDependence(ThisType(), type, identifier_token); return type; } void Semantic::ProcessInterface(AstExpression *name) { TypeSymbol *interf = MustFindType(name); assert(! interf -> SourcePending()); if (! interf -> ACC_INTERFACE()) { if (! interf -> Bad()) { ReportSemError(SemanticError::NOT_AN_INTERFACE, name -> LeftToken(), name -> RightToken(), interf -> ContainingPackage() -> PackageName(), interf -> ExternalName()); } } else { TypeSymbol *this_type = ThisType(); int k; for (k = 0; k < this_type -> NumInterfaces(); k++) if (this_type -> Interface(k) == interf) break; if (k < this_type -> NumInterfaces()) { ReportSemError(SemanticError::DUPLICATE_INTERFACE, name -> LeftToken(), name -> RightToken(), interf -> ContainingPackage() -> PackageName(), interf -> ExternalName(), this_type -> ExternalName()); } else { this_type -> AddInterface(interf); } } return; } void Semantic::InitializeVariable(AstFieldDeclaration *field_declaration, Tuple<VariableSymbol *> &finals) { ThisMethod() = NULL; for (int i = 0; i < field_declaration -> NumVariableDeclarators(); i++) { AstVariableDeclarator *variable_declarator = field_declaration -> VariableDeclarator(i); if (ThisVariable() = variable_declarator -> symbol) { if (variable_declarator -> variable_initializer_opt) { variable_declarator -> pending = true; int start_num_errors = NumErrors(); ProcessVariableInitializer(variable_declarator); if (NumErrors() == start_num_errors) DefiniteVariableInitializer(variable_declarator, finals); else variable_declarator -> symbol -> MarkDefinitelyAssigned(); // assume variable is assigned variable_declarator -> pending = false; } ThisVariable() -> MarkComplete(); } } return; } inline void Semantic::ProcessInitializer(AstBlock *initializer_block, AstBlock *block_body, MethodSymbol *init_method, Tuple<VariableSymbol *> &finals) { ThisVariable() = NULL; ThisMethod() = init_method; LocalBlockStack().Push(initializer_block); LocalSymbolTable().Push(init_method -> block_symbol -> Table()); int start_num_errors = NumErrors(); AstConstructorBlock *constructor_block = block_body -> ConstructorBlockCast(); if (constructor_block) { assert(constructor_block -> explicit_constructor_invocation_opt); ReportSemError(SemanticError::MISPLACED_EXPLICIT_CONSTRUCTOR_INVOCATION, constructor_block -> explicit_constructor_invocation_opt -> LeftToken(), constructor_block -> explicit_constructor_invocation_opt -> RightToken()); } ProcessBlock(block_body); if (NumErrors() == start_num_errors) DefiniteBlockInitializer(block_body, LocalBlockStack().max_size, finals); // // If an enclosed block has a higher max_variable_index than the current block, // update max_variable_index in the current_block, accordingly. // if (init_method -> block_symbol -> max_variable_index < LocalBlockStack().TopMaxEnclosedVariableIndex()) init_method -> block_symbol -> max_variable_index = LocalBlockStack().TopMaxEnclosedVariableIndex(); LocalBlockStack().Pop(); LocalSymbolTable().Pop(); return; } void Semantic::ProcessStaticInitializers(AstClassBody *class_body) { if (class_body -> NumStaticInitializers() > 0 || class_body -> NumClassVariables() > 0) { TypeSymbol *this_type = ThisType(); MethodSymbol *init_method = this_type -> InsertMethodSymbol(control.clinit_name_symbol); init_method -> SetType(control.void_type); init_method -> SetACC_FINAL(); init_method -> SetACC_STATIC(); init_method -> SetContainingType(this_type); init_method -> SetBlockSymbol(new BlockSymbol(0)); // the symbol table associated with this block will contain no element init_method -> block_symbol -> max_variable_index = 0; init_method -> SetSignature(control); this_type -> static_initializer_method = init_method; AstBlock *initializer_block = compilation_unit -> ast_pool -> GenBlock(); initializer_block -> left_brace_token = class_body -> left_brace_token; initializer_block -> right_brace_token = class_body -> left_brace_token; initializer_block -> block_symbol = init_method -> block_symbol; initializer_block -> nesting_level = LocalBlockStack().Size(); LocalBlockStack().max_size = 0; // // Compute the set of final variables declared by the user in this type. // Tuple<VariableSymbol *> finals(this_type -> NumVariableSymbols()); for (int l = 0; l < this_type -> NumVariableSymbols(); l++) { VariableSymbol *variable_symbol = this_type -> VariableSym(l); if (variable_symbol -> ACC_FINAL()) finals.Next() = variable_symbol; } // // The static initializers and class variable initializers are executed in textual order... 8.5 // int j, k; for (j = 0, k = 0; j < class_body -> NumClassVariables() && k < class_body -> NumStaticInitializers(); ) { // // Note that since there cannot be any overlap in the // declarations, we can use either location position. // The RightToken of the field declaration is used because it // does not have to be computed (it is the terminating semicolon). // Similarly, the LeftToken of the static initializer is used // because it is the initial "static" keyword that marked the initializer. // // if (class_body -> InstanceVariables(j) -> RightToken() < class_body -> Block(k) -> LeftToken()) // if (class_body -> ClassVariable(j) -> semicolon_token < class_body -> StaticInitializer(k) -> static_token) { InitializeVariable(class_body -> ClassVariable(j), finals); j++; } else { AstBlock *block_body = class_body -> StaticInitializer(k) -> block; // // The first block that is the body of an initializer is reachable // A subsequent block is reachable iff its predecessor can complete // normally // block_body -> is_reachable = (k == 0 ? true : class_body -> StaticInitializer(k - 1) -> block -> can_complete_normally); ProcessInitializer(initializer_block, block_body, init_method, finals); k++; } } for (; j < class_body -> NumClassVariables(); j++) InitializeVariable(class_body -> ClassVariable(j), finals); for (; k < class_body -> NumStaticInitializers(); k++) { AstBlock *block_body = class_body -> StaticInitializer(k) -> block; // // The first block that is the body of an initializer is reachable // A subsequent block is reachable iff its predecessor can complete // normally // block_body -> is_reachable = (k == 0 ? true : class_body -> StaticInitializer(k - 1) -> block -> can_complete_normally); ProcessInitializer(initializer_block, block_body, init_method, finals); } init_method -> max_block_depth = LocalBlockStack().max_size; init_method -> block_symbol -> CompressSpace(); // space optimization // // Check that all static final variables have been initialized by now. // If not, issue an error and assume they are. // for (int i = 0; i < finals.Length(); i++) { if (finals[i] -> ACC_STATIC() && (! finals[i] -> IsDefinitelyAssigned())) { ReportSemError(SemanticError::UNINITIALIZED_STATIC_FINAL_VARIABLE, finals[i] -> declarator -> LeftToken(), finals[i] -> declarator -> RightToken()); finals[i] -> MarkDefinitelyAssigned(); } } // STG: // delete initializer_block; } return; } void Semantic::ProcessBlockInitializers(AstClassBody *class_body) { TypeSymbol *this_type = ThisType(); // // Compute the set of final variables declared by the user in this type. // Tuple<VariableSymbol *> finals(this_type -> NumVariableSymbols()); for (int i = 0; i < this_type -> NumVariableSymbols(); i++) { VariableSymbol *variable_symbol = this_type -> VariableSym(i); if (variable_symbol -> ACC_FINAL()) finals.Next() = variable_symbol; } // // Initialization code is executed by every constructor, just after the // superclass constructor is called, in textual order along with any // instance variable initializations. // if (class_body -> NumBlocks() == 0) { for (int j = 0; j < class_body -> NumInstanceVariables(); j++) InitializeVariable(class_body -> InstanceVariable(j), finals); } else { MethodSymbol *init_method = this_type -> InsertMethodSymbol(control.block_init_name_symbol); init_method -> SetType(control.void_type); init_method -> SetACC_FINAL(); init_method -> SetACC_PRIVATE(); init_method -> SetContainingType(this_type); init_method -> SetBlockSymbol(new BlockSymbol(0)); // the symbol table associated with this block will contain no element init_method -> block_symbol -> max_variable_index = 1; init_method -> SetSignature(control); // // Compute the set of constructors whose bodies do not start with // an explicit this call. // for (int i = 0; i < class_body -> NumConstructors(); i++) { MethodSymbol *method = class_body -> Constructor(i) -> constructor_symbol; if (method) { AstConstructorBlock *constructor_block = class_body -> Constructor(i) -> constructor_body; if (! (constructor_block -> explicit_constructor_invocation_opt && constructor_block -> explicit_constructor_invocation_opt -> ThisCallCast())) init_method -> AddInitializerConstructor(method); } } this_type -> block_initializer_method = init_method; AstBlock *initializer_block = compilation_unit -> ast_pool -> GenBlock(); initializer_block -> left_brace_token = class_body -> left_brace_token; initializer_block -> right_brace_token = class_body -> left_brace_token; initializer_block -> block_symbol = init_method -> block_symbol; initializer_block -> nesting_level = LocalBlockStack().Size(); LocalBlockStack().max_size = 0; int j, k; for (j = 0, k = 0; j < class_body -> NumInstanceVariables() && k < class_body -> NumBlocks(); ) { // // Note that since there cannot be any overlap in the // declarations, we can use either location position. // The RightToken of the field declaration is used because it // does not have to be computed (it is the terminating semicolon). // Similarly, the LeftToken of the block initializer is used // because it is the initial "{". // // if (class_body -> InstanceVariable(j) -> RightToken() < class_body -> Blocks(k) -> LeftToken()) // if (class_body -> InstanceVariable(j) -> semicolon_token < class_body -> Block(k) -> left_brace_token) { InitializeVariable(class_body -> InstanceVariable(j), finals); j++; } else { AstBlock *block_body = class_body -> Block(k); // // The first block that is the body of an initializer is reachable // A subsequent block is reachable iff its predecessor can complete // normally // block_body -> is_reachable = (k == 0 ? true : class_body -> Block(k - 1) -> can_complete_normally); ProcessInitializer(initializer_block, block_body, init_method, finals); k++; } } for (; j < class_body -> NumInstanceVariables(); j++) InitializeVariable(class_body -> InstanceVariable(j), finals); for (; k < class_body -> NumBlocks(); k++) { AstBlock *block_body = class_body -> Block(k); // // The first block that is the body of an initializer is reachable // A subsequent block is reachable iff its predecessor can complete // normally // block_body -> is_reachable = (k == 0 ? true : class_body -> Block(k - 1) -> can_complete_normally); ProcessInitializer(initializer_block, block_body, init_method, finals); } init_method -> max_block_depth = LocalBlockStack().max_size; init_method -> block_symbol -> CompressSpace(); // space optimization // // Note that unlike the case of static fields. We do not ensure here that // each final instance variable has been initialized at this point, because // the user may chose instead to initialize such a final variable in every // constructor instead. See body.cpp // // STG: // delete initializer_block; } return; }