/* -*- c++ -*- */ /* decls.h: Decls: information for the symbol table */ #ifndef _DECLS_H_ #define _DECLS_H_ #include #include #include #include "MethodSet.h" #include "Subst.h" #include "common.h" #include "ti_config.h" #include "llist.h" #include "parse.h" #include "sharing.h" class CfCode; class ClassDecl; class Decl; class MethodDecl; class TreeNode; class TypeNode; class TypeNameNode; class Environ; /* ENVIRONMENTS */ /*********************************************************************** An Environ is a mapping of names (represented by pointers to strings) to Decls (see below; a Decl represents a declaration). Names are considered identical iff they are represented by the same pointer (regardless of their contents). The mapping is actually multi-valued: the mapping of a name may be multiple declarations. This is to account for overloading of method declarations, and other instances that sometimes occur of multiple declarations for things of the same name. Environs may be NESTED: one may indicate that a certain environment E0 is nested inside E1. This affects the behavior of look-up operations: if they fail to find a given name in E0, they will (recursively) search E1. We say that a name is declared "in E0 proper" if it is found there without resorting to a search of E1. Layering gives you the effect of nested blocks or of other statements that may contain declarations that do not "escape" from the statement. To handle cases where there are multiple declarations, the method lookupFirst(name) returns an iterator of type OverloadIter that iterates over all Decls matching name in the first environment in which a match is found (if any). Thus, foriter (decl, E.lookupFirst(N), EnvironIter) { if (matchesParameters (argTypes, decl->type())) ... } might be used to find methods whose name are N that match a certain parameter list (see utils.h for a description of foriter and of this type of iterator). CONSTRUCTOR Environ() an empty environment. CONSTRUCTOR Environ (Environ* enclosing) an environment nested inside ENCLOSING. METHOD lookup (string* name)->Decl* METHOD lookup (string* name, int mask)->Decl* METHOD lookup (string* name, bool& more)->Decl* METHOD lookup (string* name, bool& more, int mask)->Decl* the first definition of NAME in *this, or NULL if there is none. If MORE is specified, it is set to TRUE iff there are more declarations of NAME in the same frame. The MASK operand, when present, restricts the search to Decls whose category (see below) is in MASK (that is, Decl*s, d, such that (d->category() & MASK) != 0.). METHOD lookupProper (string* name)->Decl* METHOD lookupProper (string* name, int mask)->Decl* METHOD lookupProper (string* name, bool& more)->Decl* METHOD lookupProper (string* name, bool& more, int mask)->Decl* same as lookup, but returns only Decls in *this proper. METHOD lookupFirst (string* name)->EnvironIter METHOD lookupFirst (string* name, int mask)->EnvironIter a "Hilfinger standard iterator" (HSI, see utils.h) that enumerates all declarations matching NAME in the first frame in which it is found. MASK is as for lookup, above. METHOD lookupFirstProper (string* name)->EnvironIter METHOD lookupFirstProper (string* name, int mask)->EnvironIter as for lookupFirst, but looks only for declarations proper to *THIS. METHOD allDecls()->EnvironIter an HSI that enumerates all declarations in *this, including declarations in Environs in which *this is nested. METHOD allProperDecls()->AllDeclIter an HSI that enumerates all declarations in *this proper. METHOD add (Decl* decl); adds a mapping DECL->name()->DECL in *this proper. It does not affect any Environs in which *this is nested. **********************************************************************/ class EnvironEntry { friend class Environ; friend class EnvironIter; public: EnvironEntry(); Decl* decl() const { return _decl; } const string* name() const { return _name; } protected: EnvironEntry(const string* name, Decl* decl); EnvironEntry(Decl* decl); const string* _name; Decl* _decl; }; class EnvironIter { friend class Environ; public: EnvironIter(); /* EnvironIter (const EnvironIter&); (defaulted) */ /* EnvironIter& operator= (const EnvironIter&); (defaulted) */ Decl& operator*() const { return *((*here)->decl()); } Decl* operator->() const { return (*here)->decl(); } bool isDone() const { return here == end; } void next(); protected: EnvironIter (Environ* next0, vector::const_iterator begin0, vector::const_iterator end0, const string* name0, int mask0); Environ* _next; vector::const_iterator here, end; const string* name; int mask; void skip(); }; class Environ { friend class EnvironIter; public: Environ (Environ* nestedIn = NULL); Environ *parent() const { return next; } void copy(Environ *from); Decl* lookup (const string* name, int categoryMask = -1) const; Decl* lookup (const string* name, bool& more, int categoryMark = -1) const; Decl* lookupProper (const string* name, int categoryMask = -1) const; Decl* lookupProper (const string* name, bool& more, int categoryMask = -1) const; EnvironIter lookupFirst (const string* name, int categoryMask = -1) const; EnvironIter lookupFirstProper (const string* name, int categoryMask = -1) const; EnvironIter allDecls(int categoryMask = -1) const; EnvironIter allProperDecls(int categoryMask = -1) const; void add (Decl* decl); void add (const string* name, Decl* decl); void print (ostream& os) const; void printProper (ostream& os) const; private: vector decls; Environ* next; }; /* Returns true if env has more than one entry */ bool moreThanOne (EnvironIter env); /* DECLARATIONS (DECLS) */ /*********************************************************************** A Decl encapsulates information about a declaration of some entity. There is a unique Decl for each Decl in the compilation. The class Decl declares many members, most of which make sense only for certain types of Decl. Attempts to access nonsensical members will cause runtime errors. By convention, a Decl member named "foo" will return the "foo" attribute when called with no parameters, and set the "foo" attribute when called with one parameter. Thus, decl->type() is the type of the entity referred to by decl (a Decl, presumably), and decl->foo(aType) sets the type attribute of decl to aType. Also, if member "foo" is not valid for all Decls, there is a member "hasFoo()" that returns true or false depending on whether object on which it is called has a class for which "foo" may be called. Objects of type Decl should not be allocated; the class is intended as a base class for others. METHOD name() All Decls have a name, of type const string*. These are the unique representative strings assigned by lexical analysis. The names of two Decls are considered the same iff they are the same pointer, ignoring contents: names that are different pointers to strings containing the same characters are considered distinct. METHOD container(), container (declp) Members, classes, interfaces, and packages are all parts of some larger declared entity, which is their container. Members are contained in classes and interfaces, which are themselves contained in packages, which are in turn contained in other packages. Outer-level packages have as their container the special Decl* PackageDecl::System. METHOD type(), type (typep) Decls of entities that "have a type"---such as local variables, parameters, fields, and methods---define this member. Types are represented as pointers to AST nodes of type TypeNode, just as they are during parsing. Packages, statement labels, classes, and interfaces don't have types (although the latter two ARE types). METHOD modifiers(), modifiers (mods) Classes, interfaces, and their members have modifiers, as defined by Common::Modifiers; METHOD environ(), environ (env) Classes, interfaces, and packages define environments: mappings of names (of members, classes, interfaces, and subpackages) to Decls of these entities. METHOD source(), source (tree) Decls that come from the current compilation have some piece of the AST associated with them. For example, a Decl for a local variable is created in response to a VarDeclNode. That VarDeclNode becomes the source() attribute of LocalVarDecl created to stand for that declaration. ClassDecls have a a ClassDeclNode as their source(), and so on. Decls that arise as the result of importing a class have special dummy source nodes created for them. METHOD superClass(), superClass (decl) The Decl* of the superclass of the class represented by a Decl. Defined by type ClassDecl. METHOD interfaces(), interfaces (ints) An llist giving the set of all interfaces that this class extends or implements. Defined by type ClassDecl. METHOD requires(), requires (decl) A list of other classes used by this class. Defined by type ClassDecl. METHOD valid(), valid (b) A boolean used to represent whether a class or interface is valid or not (valid == no circularity in inheritance/extends) METHOD isType() True for Decls that represent classes or interfaces. METHOD asType() For Decls for which isType() is true, a resolved TypeNameNode* that stands for the type this class represents. That is, it is a TypeNameNode whose decl() is THIS. METHOD signature() For Decl of types and packages, the JVM representation of *THIS as a signature. METHOD thisClassName() A const char* that identifies this class for messages. METHOD category() A Decl::Category (see below) that serves as a first-class type tag. METHOD forwardto(args) Do template instantiation on this Decl, with args giving the template arguments. METHOD string fullName(delimiter) Return a string giving the full name (including class, etc) of this Decl. Optional delimiter will appear between nested components and defaults to a period. METHOD string mangledFullName( first_time ) Return a string giving the full name (including class, etc) of this Decl using mangling. "first_time" is set to true if this is the outermost mangling. METHOD errorName() Return a string representing this Decl suitable for printing in an error message. METHOD drequire() Ensure that the source code for this ClassDecl is loaded (undefined on all other decls) METHOD overrides(), overrides (d) Methods indicate which declaration D they override/hide. NULL if this is the initial definition of the method METHOD implements(), implements (d) Methods indicate which interface methods they implement. Similar to overrides(), but refers to a set of interface methods rather than a single superclass method. METHOD assignable() TRUE if the entity declared is assignable (meaningful only for variable or field decls. Foreach control points are not assignable, local and formals can be declared "final". Locals are not yet supported (needs definite assignment implementation). **********************************************************************/ class Decl { protected: /* A new Decl of an entity named NAME0 . If NAME0 is null, then */ /* name() is set to a special string and erroneous() is true. (see */ /* below). Otherwise, erroneous is false. */ Decl (const string* name0); public: typedef Common::Modifiers Modifiers; /* Tags identifying categories of Decl (declaration). */ enum Category { Class = 1 << 0, /* Type ClassDecl representing a class */ Interface = 1 << 1, /* Type ClassDecl representing an interface */ Field = 1 << 2, /* Type FieldDecl */ Method = 1 << 3, /* Type MethodDecl */ Constructor = 1 << 4, /* Type MethodDecl */ LocalVar = 1 << 5, /* Type LocalVarDecl */ Formal = 1 << 6, /* Type FormalParameterDecl */ Package = 1 << 7, /* Type PackageDecl */ StmtLabel = 1 << 8, /* Type StmtLblDecl */ Primitive = 1 << 9, /* Type PrimitiveDecl */ Template = 1 << 10, /* Type TemplateDecl */ ConstPseudonym = 1 << 11, /* Type ConstPseudonymDecl */ TypePseudonym = 1 << 12 /* Type TypePseudonymDecl */ }; const string* name() const { return _name; } virtual const string* declaredName() const { return _name; } virtual void drequire(); virtual Decl* container() const; virtual void container (Decl* decl); virtual bool hasContainer() const; virtual TypeNode* type() const; virtual void type (TypeNode* typ); virtual bool hasType() const; virtual Common::Modifiers modifiers() const; virtual void modifiers (Common::Modifiers mods); virtual bool hasModifiers() const; virtual TreeNode* source() const; virtual void source (TreeNode* tree); virtual bool hasSource() const; virtual Environ* environ(); virtual void environ (Environ* env); virtual bool hasEnviron() const; // This is used only by ClassDecl. virtual Environ *environ(bool build); virtual ClassDecl* superClass() const; virtual void superClass(ClassDecl* decl); virtual bool hasSuperClass(); virtual llist* interfaces(); virtual void interfaces (llist* ints); virtual bool hasInterfaces() const; virtual Decl* overrides() const; virtual void overrides(Decl* decl); virtual bool hasOverrides() const; virtual bool hasImplements() const; virtual MethodSet &implements(); virtual const MethodSet &implements() const; virtual void implements(MethodDecl* decl); virtual bool hasOverriders() const; virtual MethodSet *overriders(); virtual const MethodSet *overriders() const; virtual void overriders(MethodDecl* decl); virtual bool broken() const; virtual void broken(bool broke); virtual bool continued() const; virtual void continued(bool cont); virtual void requires(Decl &); virtual void requires(TypeNode &); typedef set< pair > DeclIntSet; virtual DeclIntSet *initDepends(); virtual void initDepends(Decl *, int); virtual DeclIntSet *dependsOnInit(); virtual void dependsOnInit(Decl *, int); virtual bool valid() const; virtual void valid (bool now); virtual TypeNode* asType() const; virtual bool isType() const; virtual string signature() const; virtual const char* thisClassName() const = 0; virtual string cFieldName() const; virtual Category category() const = 0; // Qualification inference void localEnactFromType(); void sharingEnactFromType(); /* A general-purpose flag (initial value 0) that may be used to */ /* record how complete the information in this Decl is. */ int visits; int mark; // Query methods to determine how complete the information in this Decl is virtual bool isTypeReady() const { return true; } virtual bool typesResolved() const { return true; } virtual bool isFieldReady() const { return true; } virtual bool isMethodReady() const { return true; } // Information on template instances (arguments only, the actual // template is found via source() until it is finally substituted) virtual Subst *templateArgs(); virtual void templateArgs(Subst *args); virtual bool isTemplateBasis() const; /* Return a string giving the full name (including class, etc) of this decl */ virtual string fullName( char = '.' ); virtual string mangledFullName( bool first = 1 ); /* Return the mangled name for this decl ignoring its containers */ virtual string mangledName( bool first = 1 ); /* Return a string representing this decl suitable for printing */ /* in an error message */ virtual string errorName(); // Name for interface table in generated C code. // Implemented only by ClassDecl. virtual const string cIntfMTName(); // Source containing class's native methods. // Implemented only by ClassDecl. virtual const string cNativeName(); // Name for a method, resolved statically. // Implemented only by MethodDecl. virtual const string cMethodNameStatic() const; virtual const string cMethodNameDynamic() const; void print (ostream& os) const; void dump (ostream& os) const; /* True if this is a dummy Decl produced as a placeholder for an */ /* erroneous declaration. */ bool erroneous() const; virtual Decl *forwardto(TreeNode *src); virtual Decl *memberforward(Subst *args); // code fragment generators // defined only by ClassDecl virtual void includeSelf(CfCode &); virtual void includeSupers(CfCode &); Decl *forward() { return _forward ? _forward : this; } void forward(Decl *d) { _forward = d; } virtual bool assignable() { return true; } virtual ~Decl() {} protected: void fatal (const string& msg) const __attribute__((noreturn)); void invalidOperation (const char* opname) const __attribute__((noreturn)); // subclass-specific dump helper virtual void dumpAttributes( ostream & ) const = 0; private: /* Copying or assigning a declaration is illegal. Most accidental */ /* attempts to do so will attempt to invoke one of these operations */ /* and fail at compilation time. */ Decl(const Decl&); Decl& operator= (const Decl&); const string* const _name; Decl *_forward; }; /* Individual kinds of Decl */ class PackageDecl : public Decl { public: /* The 'package' containing all outer-level packages. */ static PackageDecl* const System; PackageDecl (const string* name, Decl* container = System) : Decl(name), _container (container), _environ (NULL), isStub (true) {} bool hasEnviron() const { return true; } Environ* environ() { if (isStub) readIn(); return _environ; } void environ (Environ* env) { isStub = false; _environ = env; } bool hasContainer() const { return true; } Decl* container() const { return _container; } void container (Decl* decl) { _container = decl; } const char* thisClassName() const; Category category() const; string signature() const; string mangledFullName( bool ); string errorName(); protected: void dumpAttributes( ostream & ) const; Decl* _container; Environ* _environ; bool isStub; void readIn(); }; class LocalVarDecl : public Decl { public: LocalVarDecl (const string* name, TypeNode* type, TreeNode* source, bool assignable) : Decl (name), _type (type), _source (source), _assignable (assignable) {} bool hasType() const { return true; } TypeNode* type() const { return _type; } void type (TypeNode* type0) { _type = type0; } bool hasSource() const { return true; } TreeNode* source() const { return _source; } void source (TreeNode* tree) { _source = tree; } const char* thisClassName() const; Category category() const; string errorName(); Decl *forwardto(TreeNode *src); virtual bool assignable() { return _assignable; } protected: void dumpAttributes( ostream & ) const; TypeNode* _type; TreeNode* _source; bool _assignable; }; class FormalParameterDecl : public Decl { public: FormalParameterDecl (const string* name, TypeNode* type, TreeNode* source, bool assignable) : Decl (name), _type (type), _source (source), _assignable (assignable) {} bool hasType() const { return true; } TypeNode* type() const { return _type; } void type (TypeNode* type0) { _type = type0; } bool hasSource() const { return true; } TreeNode* source() const { return _source; } void source (TreeNode* tree) { _source = tree; } const char* thisClassName() const; Category category() const; string errorName(); Decl *forwardto(TreeNode *src); virtual bool assignable() { return _assignable; } protected: void dumpAttributes( ostream & ) const; TypeNode* _type; TreeNode* _source; bool _assignable; }; class StmtLblDecl : public Decl { public: StmtLblDecl (const string* name, TreeNode* source) : Decl (name), _source (source) {} bool hasSource() const { return true; } TreeNode* source() const { return _source; } void source (TreeNode* tree) { _source = tree; } const char* thisClassName() const; Category category() const; string errorName(); virtual bool broken() const; virtual void broken(bool broke); virtual bool continued() const; virtual void continued(bool cont); Decl *forwardto(TreeNode *src); protected: void dumpAttributes( ostream & ) const; TreeNode* _source; bool _broken; bool _continued; }; /* Type manipulation */ /* True iff the class represented by ACLASS implements the interface */ /* represented by INTERFACE. */ extern bool implements (Decl* aClass, Decl* interface); /* True iff the interface represented by DECL0 is a superinterface of */ /* (is extended by) the interface represented by DECL1. */ extern bool isSuperInterface (Decl* decl0, Decl* decl1); /* True iff the interface represented by DECL0 is a subclass of */ /* the interface represented by DECL1. */ bool isSubClass(Decl *decl0, Decl *decl1); /* Assuming that M0 and M1 are MethodDecls, true iff M0 is more specific */ /* (in the sense of 14.11.2.2) than M1. Actually, the right term */ /* should be "no less specific than", but the Reference Manual is the */ /* Reference Manual. */ extern bool isMoreSpecific (const Decl* M0, const Decl* M1); /* Given the fully-qualified name of a class, return the Decl for it. */ extern Decl* declFromFullClassName (string name); /* Resolve NAME (if not already resolved) with a matching Decl from */ /* ENV whose category() is one of CATEGORIES. Fill in NAME's decl() */ /* attribute with the first such Decl*, and set the global RESOLUTIONS */ /* to an iterator over all matches. For objects, returns a node for */ /* accesssing NAME---an ObjectNode, ThisFieldAccessNode, or */ /* ObjectFieldAccessNode. Otherwise returns the modified NAME. */ extern TreeNode* resolveAName (TreeNode* name, Environ& env, TypeNode *currentClass, Common::Modifiers thisModifiers, Decl *currentPackage, int categories, bool canonical = false); extern TreeNode* resolveAName (TreeNode* name, Environ& env, TypeNode *currentClass, Common::Modifiers thisModifiers, Decl *currentPackage, bool &postponed, int categories, bool canonical = false); EnvironIter qualifiedLookup(TreeNode *name, Environ& env, TypeNode *currentClass, Common::Modifiers thisModifiers, Decl *currentPackage, int categories, bool canonical = false); EnvironIter qualifiedLookup(TreeNode *name, Environ& env, TypeNode *currentClass, Common::Modifiers thisModifiers, Decl *currentPackage, bool &postponed, int categories, bool canonical = false); /* Resolve a call to one of the METHODS, based on ARGS actual arguments and ACTUALFLAGS modifiers on the actual dispatch object. Report errors for no matching methods and ambiguous method calls. Return (one of) the matching methods, or UnknownMethodDecl if no matching method exists. Return null if any argument's type is not yet resolved. */ Decl* resolveCall(EnvironIter methods, Common::Modifiers actualFlags, TreeNode *args, SourcePosn posn, bool printFirst = true); // changed /* If calls to method can have global effects, return one of the methods that may be called that can have global effects (i.e. which has the Sglobal modifier). Otherwise return NULL */ Decl *isGlobalCall(Decl *method); /* Dummy Decl's whose purpose is to serve as placeholders when a */ /* static semantic error occurs. */ extern ClassDecl* UnknownClassDecl; extern Decl* UnknownPackageDecl; extern Decl* UnknownFieldDecl; extern Decl* UnknownMethodDecl; #define isLocalOrParam(decl) \ ((decl)->category() & (Decl::LocalVar | Decl::Formal)) extern void printNode (const Decl*, ostream&); #endif