|
ESC/Java2 © 2003,2004,2005,2006 David Cok and Joseph Kiniry © 2005,2006 UCD Dublin © 2003,2004 Radboud University Nijmegen © 1999,2000 Compaq Computer Corporation © 1997,1998,1999 Digital Equipment Corporation All Rights Reserved |
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||||
java.lang.Objectjavafe.ast.ASTNode
javafe.ast.Type
javafe.tc.TypeSig
A TypeSig is a proxy and adaptor for TypeDecl.
They are proxies because, during name resolution, TypeName objects are
resolved to point to TypeSig objects rather than directly
to TypeDecl objects. This gives us the flexibility of
deferring parsing of a type declaration until we know we need detailed
information about it.
They are adaptors because they provide extra functionality not provided
by TypeDecl objects. In particular, they provide lookup
methods that allow clients to find particular members of a type
declaration (including inherited members), and resolve methods that
perform name resolution inside the implementation of a type
declaration.
What about the fact that we are a subtype of Type?
TypeSig objects are meant to be "interned"; that is, for
each canonical TypeDecl, we want there to be exactly
one associated TypeSig object. The first
TypeDecl loaded by the system for a given typename is
considered to be the canonical TypeDecl for that typename;
all other TypeDecls for that typename are considered
non-canonical.
To achieve this interning, clients of the javafe.tc package
should not directly create TypeSig objects; rather, they
should rely on javafe.tc to create TypeSig
objects for them. Similarly, clients of the javafe.tc
package should rely on javafe.tc to do the parsing
necessary to create instances of TypeDecl. Not only will
the javafe.tc package intern TypeSig objects,
it will also ensure that, for TypeSig s and TypeDecl
d,
s.getTypeDecl() is always a canonical TypeDecl
s.getTypeDecl().sig == s
d is canonical then d.sig.getTypeDecl()==d
d is not canonical then d.sig is the
TypeSig associated with d's typename.javafe.tc
package?
Resolving the names in a type declaration and checking its static semantics usually involves looking at other declarations to which it refers. Finding, reading, and processing referred-to types makes resolution and checking fairly complicated. As a result, we have decomposed it into smaller steps. Type declarations move through a number of states as the resolution and checking process proceeds. In addition to making the overall processing of type declarations conceptually more manageable, this decomposition has two other benefits:
TypeSig object moves during its lifetime. Most clients of
the javafe.tc package do not need to know about these
details. However, clients interested in extending the processing done
by the javafe.tc package may need to add other states as
well. Also, this documentation gives an overview of the
javafe.tc package for those interested in understanding its
implementation.
TypeSigs start in the TypeSig created
state then move sequentially through the following four states:
parsed, supertype links resolved, prepped, and
checked. Each following state represents additional processing
completed on top of the processing required for the previous state. A
description of these states in reverse order follows. Included are the
properties that hold in each state; these properties are "additive":
properties of states later in the list are also properties of states
earlier in the list.
TypeCheck for the
definitions of disambiguation, resolution, and checking).
Transitioning to this state can trigger parsing and/or preparation of
types referenced (where?) either explicitly or implicitly.
Implicitly referenced types are types used but not explicitly
mentioned in a TypeName node (huh?); for example,
the type of the result of foo in the expression
"bar(x.foo())" is implicitly referenced by this
expression.
TypeSigs
in the prepped state have had such work done on their declarations,
preparing them for having their members queried. As a convenience, the
methods of TypeSig that lookup the members of a type
declaration, such as lookupField and lookupMethod, automatically
transition the declaration (TypeSig?) to the prepped
state if it isn't there already.
When preparing the declaration associated with a TypeSig,
it is also useful to report certain errors in it, such as two fields
with the same name. This way, when checking a class, the user will also
see a report of errors in the interfaces (but not the implementations)
of the classes used by the class being checked.
The prepped state is supertype transitive: a state X is
supertype transitive if a TypeSig can only be in state
X if all its supertypes are at least in state X. Note
that there is no requirement that X's type members be in any
particular state.
TypeNames, which are
symbolic references. Resolution of a TypeName object
involves pointing its sig field to the TypeSig
object for the type declaration to which the TypeName
symbolically refers. Resolving the supertype links of type declarations
separately from preparing them allows us to perform supertype checks
during the preparation process.
As a convenience, the isSubtypeOf method of
TypeSig, which performs the supertype test, automatically
resolves supertype links if they have not been resolved already.
Like the prepped state, the "supertype links resolved" state is supertype transitive.
TypeSigs come into
existence when their type declarations are parsed, some of them can be
created earlier. Thus, we can distinguish TypeSigs that
have been parsed from those that have not. However, it is difficult for
a client outside javafe.tc to know whether or not a
TypeSig has been parsed. This is because, if a client
calls getTypeDecl on a
TypeSig that has not been parsed, it will be parsed
automatically.
TypeSig created. This is the initial state
of TypeSig objects that come into existence before their
corresponding declarations have been parsed. Again, it is it is
difficult for a client outside javafe.tc to to distinguish
between this state and the parsed state.This section contains a few more details about the implementation for those who wish to understand it.
Inside the javafe.tc package, creation of
TypeSig and TypeDecl objects is managed by
the OutsideEnv
class. Methods of this class take the fully-qualified name of
an "package-member type" -- that is, a type declaration not nested
inside another declaration -- and return the TypeSig
instance associated with the type declaration denoted by that name.
OutsideEnv also coordinates the parsing of type
declarations, ensuring that only one TypeDecl is
created for a type declaration, and ensuring that
TypeSig objects point to the appropriate
TypeDecl objects.
The OutsideEnv uses direct instances of
TypeSig for nested types only. It uses a special subclass
of TypeSig, TopTypeSig, for externally
nameable types (what the Java spec calls "top-level types"). This
subclass has fields giving the types external name. A further subclass
of TopTypeSig, OutsideTypeSig, handles outside
types. Alone among TypeSigs, OutsideTypeSigs
have the the ability to load their TypeDecl objects lazily.
All other TypeSig classes must have their
TypeDecl provided at creation time. However, this is an
implementation issue only: clients outside of javafe.tc
should not assume the existence of these subclasses.
Transitioning a TypeSig from one state to another may
require parsing and processing of other types such as supertypes or the
types found in method signatures. For example, checking that the
throws clause of a method override is legal may involve
checking a subtype relationship, which requires that types involved be
supertype-link resolved. We call transitions that arise in the process
of another transitions "secondary transitions." The code that
implements transitions does not have to explicitly invoke secondary
transitions; rather, they are performed by calling methods like
lookupField or isSubtypeOf, whose
implementations do invoke transitions if they are needed. For
example, the method that implements the preparation transition does not
directly call the method that implements supertype link resolution, but
it does call isSubtypeOf, which in turn does
directly call the supertype link resolution method. Thus, secondary
transitions are largely transparent to the code implementing each
transition, with one exception. The code implementing the transition to
one state cannot invoke methods that automatically transition
types to a higher state. For example, the code implementing supertype
link resolution cannot call lookupField. This discipline
helps us avoid looping.
OutsideEnv,
TypeCheck,
TypeDecl,
TypeName| Field Summary | |
static int |
CHECKED
|
static int |
CREATED
* TypeSig states and transition functions: * * |
protected CompilationUnit |
CU
The CompilationUnit we belong to; null iff myTypeDecl is null because of laziness. |
protected Env |
enclosingEnv
Our enclosing Env; may be null for member types because of laziness. |
TypeSig |
enclosingType
Our enclosing type or null iff we are a package-member type. |
protected FieldDeclVec |
fields
After preparation, this field contains all field members of the TypeDecl associated with this,
including inherited ones. |
protected FieldDeclVec |
hiddenfields
|
static int |
LINKSRESOLVED
|
private static java.util.Hashtable |
map
The map from fully-qualified external names of package-member types to the TypeSigs representing them. |
boolean |
member
Are we a direct member of a package or a type? |
protected MethodDeclVec |
methods
After preparation, this field contains all method members of the TypeDecl associated with this,
including inherited ones. |
protected TypeDecl |
myTypeDecl
Our TypeDecl; may be null only for package-member type because of laziness. |
java.lang.String[] |
packageName
The name of the package we belong to. |
static int |
PARSED
|
static int |
PREPPED
|
static int |
RESOLVINGLINKS
|
static ASTDecoration |
sigDecoration
Decorates TypeDecl nodes to point to
TypeSig objects. |
java.lang.String |
simpleName
Our simple name or null if we are an anonymous type. |
int |
state
The current state of this. |
private TypeSig |
superClass
|
static java.lang.String |
THE_UNNAMED_PACKAGE
|
| Fields inherited from class javafe.ast.Type |
tmodifiers |
| Fields inherited from class javafe.ast.ASTNode |
bogusField, dotCounter, dotId |
| Constructor Summary | |
protected |
TypeSig(java.lang.String[] packageName,
java.lang.String simpleName,
TypeDecl decl,
CompilationUnit CU)
Create a TypeSig that represents an internal-use-only package-member type. |
protected |
TypeSig(java.lang.String[] packageName,
java.lang.String simpleName,
TypeSig enclosingType,
TypeDecl decl,
CompilationUnit CU)
Create a TypeSig that represents a member type. |
protected |
TypeSig(java.lang.String simpleName,
Env enclosingEnv,
TypeDecl decl)
Create a TypeSig that represents a non-member type. |
| Method Summary | |
void |
accept(Visitor v)
Accept a visit from v. |
java.lang.Object |
accept(VisitorArgResult v,
java.lang.Object o)
|
void |
check()
Check invariants of a TypeSig, raising an exception if they don't hold. |
java.lang.Object |
childAt(int i)
Return the first-but-ith child of a node. |
int |
childCount()
* ASTNode functions: * * |
static void |
clear()
|
void |
deepCheck()
Check invariants of a TypeSig, raising an exception if they don't hold. |
(package private) static TypeSig |
get(java.lang.String[] P,
java.lang.String T)
If a TypeSig representing the package-member type named P.T has been created, return it; otherwise, create such a TypeSig then return it. |
CompilationUnit |
getCompilationUnit()
Get the non-null CompilationUnit we are associated with. |
Env |
getEnclosingEnv()
Return our enclosing environment. |
int |
getEndLoc()
|
EnvForTypeSig |
getEnv(boolean staticContext)
Return an environment for use in checking code inside us. |
java.lang.String |
getExternalName()
Return our exact fully-qualified external name as a human-readable string suitable for display. |
FieldDeclVec |
getFields(boolean allFields)
Returns all fields of the type declaration associated with this, including inherited ones. |
FieldDeclVec |
getFieldsRaw()
|
FieldDeclVec |
getHiddenFields()
|
private static java.lang.String |
getKey(java.lang.String[] P,
java.lang.String T)
Compute the key for map for fully-qualified type P.T. |
MethodDeclVec |
getMethods()
Similar to getFields, except for methods. |
java.lang.String |
getPackageName()
Return our package name as a human-readable string suitable for display. |
static TypeSig |
getRawSig(TypeName n)
Gets the TypeSig recorded by setSig, or null. |
static TypeSig |
getSig(TypeDecl d)
The myTypeDecl field maps TypeSigs to TypeDecls. |
static TypeSig |
getSig(TypeName n)
Gets the TypeSig recorded by setSig.
|
int |
getStartLoc()
|
int |
getTag()
Return the tag of a node. |
TypeDecl |
getTypeDecl()
Get the non-null TypeDecl we are associated with. |
java.lang.String |
getTypeName()
Return our exact type name, omitting the package name, as a human-readable string suitable for display. |
boolean |
hasField(Identifier id)
TBW |
MethodDecl |
hasMethod(Identifier id,
Type[] args)
|
boolean |
inSamePackageAs(TypeSig s)
|
boolean |
isPreloaded()
Is our TypeDecl already loaded? |
boolean |
isStatic()
Are we (possibly implicitly) static? |
boolean |
isSubtypeOf(TypeSig s2)
|
boolean |
isTopLevelType()
Are we a top-level type? |
(package private) void |
load(TypeDecl decl,
CompilationUnit CU)
Load the non-null TypeDecl decl as our TypeDecl. |
static TypeSig |
lookup(java.lang.String[] P,
java.lang.String T)
If a TypeSig representing the package-member type named P.T has been created, return it; otherwise, return null. |
ConstructorDecl |
lookupConstructor(Type[] args,
TypeSig caller)
TBW |
FieldDecl |
lookupField(Identifier id,
TypeSig caller)
TBW |
TypeSig |
lookupLocalType(TypeSig caller,
Identifier id)
Do we have a type member named id (*not* including inherited type members)? |
MethodDecl |
lookupMethod(Identifier id,
Type[] args,
TypeSig caller)
TBW |
TypeSig |
lookupType(TypeSig caller,
Identifier id,
int loc)
Do we have a type member named id (including inherited type members)? |
private void |
preload()
Ensure that we have loaded our TypeDecl, invoking OutsideEnv if needed to load a TypeDecl into us via load below. |
void |
prep()
Transition this to the "prepped" state. |
void |
resolveSupertypeLinks()
Transition this to the supertype links resolved
state. |
protected void |
setDecl(TypeDecl decl,
CompilationUnit CU)
Protected routine used to associate a TypeSig with a TypeDecl. |
static void |
setSig(TypeName n,
TypeSig sig)
|
TypeSig |
superClass()
|
java.util.Collection |
superInterfaces()
|
java.lang.String |
toString()
Returns a String that represents the value of this Object. |
void |
typecheck()
Transition this to the "checked" state. |
void |
typecheckSuperTypes()
Typecheck the superclass of the current classtype being typecheck and typecheck all interfaces that the current classtype implements. |
| Methods inherited from class javafe.ast.ASTNode |
clone, clone, getDecorations, isInternal, setDecorations |
| Methods inherited from class java.lang.Object |
equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
| Field Detail |
public java.lang.String[] packageName
public TypeSig enclosingType
public java.lang.String simpleName
public boolean member
(Otherwise, we are a block-level type or an anonymous type.)
protected Env enclosingEnv
protected TypeDecl myTypeDecl
This variable should be set only using setDecl.
protected CompilationUnit CU
public static final ASTDecoration sigDecoration
TypeDecl nodes to point to
TypeSig objects.
private static final java.util.Hashtable map
Invariant: map's range includes all existing package-member TypeSigs; map sends getKey(P,T) to the unique package-member TypeSig with external name P.T.
The domain type of map is String and its range type is (non-null) TypeSigs.
public static final java.lang.String THE_UNNAMED_PACKAGE
public static final int CREATED
public static final int PARSED
public static final int RESOLVINGLINKS
public static final int LINKSRESOLVED
public static final int PREPPED
public static final int CHECKED
public int state
this. Must be one of
CREATED, PARSED,
LINKSRESOLVED, PREPPED, or
CHECKED. In most circumstances, this field
should not be written to; rather, methods of
TypeSig should be called to effect changes to it.
This field must never be decreased after creation time.
protected FieldDeclVec fields
TypeDecl associated with this,
including inherited ones.
protected FieldDeclVec hiddenfields
protected MethodDeclVec methods
TypeDecl associated with this,
including inherited ones.
private TypeSig superClass
| Constructor Detail |
protected TypeSig(java.lang.String simpleName,
Env enclosingEnv,
TypeDecl decl)
We represent a block-level type if simpleName is non-null, and an anonymous type otherwise.
protected TypeSig(java.lang.String[] packageName,
java.lang.String simpleName,
TypeSig enclosingType,
TypeDecl decl,
CompilationUnit CU)
This constructor is designed to be private to TypeSig; It is protected to support the Types inst pattern, but clients should use OutsideEnv.lookup[Deffered] and getSig to get TypeSig's representing member types.
We represent a package-member type if enclosingType is non-null, and a type-member type otherwise.
Note: packageName should never be modified by the caller after this call.
CU must be the CompilationUnit that decl belongs to.
protected TypeSig(java.lang.String[] packageName,
java.lang.String simpleName,
TypeDecl decl,
CompilationUnit CU)
This constructor should only be used by PrepTypeDeclaration.getRootInterface().
Note: packageName should never be modified by the caller after this call.
CU must be the CompilationUnit that decl belongs to.
| Method Detail |
public static TypeSig getSig(TypeDecl d)
Precondition: d has already been associated with a TypeSig.
protected void setDecl(TypeDecl decl,
CompilationUnit CU)
It automatically creates TypeSigs for any (indirect) members of decl and associates them properly.
CU must be the CompilationUnit that decl belongs to.
public static final void clear()
private static java.lang.String getKey(java.lang.String[] P,
java.lang.String T)
public static TypeSig lookup(java.lang.String[] P,
java.lang.String T)
This function should only be called by OutsideEnv.
static TypeSig get(java.lang.String[] P,
java.lang.String T)
This function should only be called by OutsideEnv.
public TypeDecl getTypeDecl()
(Under the covers, for package-member types, this method may
cause OutsideEnv to parse the
TypeDecl in question, but this should be
transparent to most clients.)
public CompilationUnit getCompilationUnit()
(Under the covers, for package-member types, this method may
cause OutsideEnv to parse the type in question,
but this should be transparent to most clients.)
private void preload()
public boolean isPreloaded()
void load(TypeDecl decl,
CompilationUnit CU)
If we have already been loaded with a different TypeDecl, then an appropriate fatal error results.
Note: This method should *only* be called by OutsideEnv.load.
CU must be the CompilationUnit that decl belongs to.
public java.lang.String getPackageName()
public java.lang.String getTypeName()
public java.lang.String getExternalName()
public java.lang.String toString()
toString in class ASTNodepublic int childCount()
childCount in class ASTNodepublic java.lang.Object childAt(int i)
ASTNode
childAt in class ASTNodepublic int getTag()
ASTNode
getTag in class ASTNodepublic void accept(Visitor v)
ASTNodev. This method simply
calls the method of v corresponding to the
allocated type of this, passing this
as the argument. See the design patterns book.
accept in class ASTNode
public java.lang.Object accept(VisitorArgResult v,
java.lang.Object o)
accept in class ASTNodepublic int getStartLoc()
getStartLoc in class ASTNodepublic int getEndLoc()
getEndLoc in class ASTNode
public TypeSig lookupType(TypeSig caller,
Identifier id,
int loc)
If we have exactly one such type member, then return it. If we have no such type member, return null. If we have more than one such type member, then if loc != Location.NULL then a fatal error is reported at that location via ErrorSet else one of the relevant type members is returned.
If caller is null, this routine does not check that the resulting type (if any) is accessible. If caller is not null, then the resulting type is checked to be accessible from the caller.
public TypeSig lookupLocalType(TypeSig caller,
Identifier id)
If caller is null, then this routine does not check that the resulting type (if any) is actually accessable. If caller is non_null, then the resulting type is checked that it is accessible from the caller.
public Env getEnclosingEnv()
public EnvForTypeSig getEnv(boolean staticContext)
Our instance members are considered accessible iff staticContext is false.
public boolean isStatic()
This differs from using Modifiers.isStatic because it does not rely on Prep'ing having added the static modifier where implicit so we can be used by Prep itself.
public boolean isTopLevelType()
True iff either we are a package-level type or a static member of a top-level type.
Note: This may be called during any state; it may bump TypeSigs to the Parsed state.
public void resolveSupertypeLinks()
this to the supertype links resolved
state. See the TypeSig type comments for details of what this involves.
A fatal error may be reported if we cannot resolve a supertype name, or detect a cycle in the type hierarchy.
public void prep()
this to the "prepped" state.
A prepped declaration has all of the TypeName
nodes defining the types of its members resolved. For a field
declaration, this means resolving the type field;
For a routine declaration, this means resolving
TypeNames that occur in the args,
raises, and returnType fields.
See the TypeSig type comments for more details of what this involves.
public void typecheck()
this to the "checked" state. See the TypeSig type comments for details of what this involves.
A fatal error may be reported if we cannot resolve a supertype name, or detect a cycle in the type hierarchy.
public void typecheckSuperTypes()
public FieldDeclVec getFields(boolean allFields)
this, including inherited ones. (If
this has not been prepped yet, this method will prep
it (possibly triggering parsing and/or processing of other
types).) If allFields is true, then all declared fields, including
hidden and inaccessible fields, are returned; if allFields is false,
then only visible fields are returned.
public FieldDeclVec getFieldsRaw()
public FieldDeclVec getHiddenFields()
public MethodDeclVec getMethods()
getFields, except for methods.
public ConstructorDecl lookupConstructor(Type[] args,
TypeSig caller)
throws LookupException
LookupException
public FieldDecl lookupField(Identifier id,
TypeSig caller)
throws LookupException
LookupExceptionpublic boolean hasField(Identifier id)
public MethodDecl hasMethod(Identifier id,
Type[] args)
public MethodDecl lookupMethod(Identifier id,
Type[] args,
TypeSig caller)
throws LookupException
LookupExceptionpublic static TypeSig getRawSig(TypeName n)
setSig, or null.
public static TypeSig getSig(TypeName n)
setSig.
Precondition: n has been resolved.
public static void setSig(TypeName n,
TypeSig sig)
public final boolean isSubtypeOf(TypeSig s2)
public final boolean inSamePackageAs(TypeSig s)
public void check()
check in class Typepublic void deepCheck()
public TypeSig superClass()
public java.util.Collection superInterfaces()
|
ESC/Java2 © 2003,2004,2005,2006 David Cok and Joseph Kiniry © 2005,2006 UCD Dublin © 2003,2004 Radboud University Nijmegen © 1999,2000 Compaq Computer Corporation © 1997,1998,1999 Digital Equipment Corporation All Rights Reserved |
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||||