001    /* Copyright 2000, 2001, Compaq Computer Corporation */
002    
003    package javafe.tc;
004    
005    import javafe.ast.*;
006    import javafe.util.*;
007    
008    
009    /**
010     * Env's are the environments used during typechecking to keep track
011     * of what types, local variables, fields, and current/enclosing
012     * instances are in scope.
013     */
014    
015    public abstract class Env {
016    
017        ///////////////////////////////////////////////////////////////////////
018        //                                                                   //
019        // Methods implemented by each instance of Env                       //
020        //                                                                   //
021        ///////////////////////////////////////////////////////////////////////
022    
023    
024        /***************************************************
025         *                                                 *
026         * Current/enclosing instances I:                  *
027         *                                                 *
028         **************************************************/
029    
030        /**
031         * Is there a current instance in scope? <p>
032         *
033         * E.g., is "this" (or "<enclosing class>.this") legal here? <p>
034         *
035         * This is also refered to as "are we in a static context?".  The
036         * legality of super also depends on this result. <p>
037         *
038         * The legality of C.this, C != <enclosing class> is different; see 
039         * canAccessInstance(-).
040         */
041        abstract public boolean isStaticContext();
042    
043    
044        /**
045         * Return the intermost class enclosing the code that is checked
046         * in this environment. <p>
047         *
048         * May return null if there is no enclosing class (aka, for
049         * environments for CompilationUnits). <p>
050         *
051         * If isStaticContext() returns true, then this is the type of "this".
052         */
053        //@ ensures (this instanceof EnvForCU) == (\result==null);
054        abstract public TypeSig getEnclosingClass();
055    
056    
057        /**
058         * If there is an enclosing instance in scope, then return the
059         * (exact) type of the innermost such instance. <p>
060         *
061         * Note: this is considered a current instance, not an enclosing
062         * instance, even inside its methods.
063         */
064        abstract public TypeSig getEnclosingInstance();
065    
066    
067        /**
068         * Returns a new Env that acts the same as us, except that its
069         * current instance (if any) is not accessible. <p>
070         *
071         * Note: this routine is somewhat inefficient and should be
072         * avoided unless an unknown environment needs to be coerced in
073         * this way. <p>
074         */
075        //@ ensures \result != null;
076        //@ ensures (this instanceof EnvForCU) == (\result instanceof EnvForCU);
077        abstract public Env asStaticContext();
078    
079    
080        /***************************************************
081         *                                                 *
082         * Simple names:                                   *
083         *                                                 *
084         **************************************************/
085    
086        /**
087         * Attempt to lookup a simple TypeName in this environment to get
088         * the TypeSig it denotes.  Returns null if no such type
089         * exists.<p>
090         *
091         * This routine does not check that the resulting type (if any)
092         * is actually accessible, if caller is null. <p>
093         *
094         * If id is ambiguous, then if loc != Location.NULL then a fatal
095         * error is reported at that location via ErrorSet else one of
096         * its possible meanings is returned.<p>
097         */
098        abstract public TypeSig lookupSimpleTypeName(
099                                    TypeSig caller, /*@ non_null @*/ Identifier id,
100                                                     int loc);
101    
102    
103        /**
104         * Locate the lexically innermost field or local variable
105         * declaration with a given name. <p>
106         *
107         * Let d be the lexically innermost field or local variable
108         * declaration (including formals) of id (if any such declaration
109         * exists).  Then this routine returns: <p>
110         *
111         *    d (a LocalVarDecl or FormalParaDecl) if d is a local
112         *                                            variable declaration
113         *
114         *    the class C that lexically encloses us and contains the
115         *    (inherited) field d if d is a field declaration
116         *
117         *    null if d does not exist
118         *
119         * Note: inherited fields are considered to lexically enclose the
120         * code of their subclasses.  We give the class containing the
121         * field instead of the field itself to postpone dealing with
122         * multiple fields named id visible in the same class.<p>
123         *
124         * In the field case, id disambiguates to C[.this].id.<p>
125         *
126         * This routine does not check that a resulting field
127         * is actually accessible. <p>
128         */
129        /*@ ensures \result==null || (\result instanceof GenericVarDecl)
130                    || (\result instanceof TypeSig); */
131        /*@ ensures \result instanceof GenericVarDecl ==>
132                           ((GenericVarDecl)\result).id == id; */
133        //@ ensures (this instanceof EnvForCU) ==> \result==null;
134        abstract public ASTNode locateFieldOrLocal(/*@ non_null @*/ Identifier id);
135    
136        public boolean isDuplicate(/*@ non_null */ Identifier id) {
137            return locateFieldOrLocal(id) instanceof GenericVarDecl;
138        }
139    
140        /**
141         * Locate the lexically innermost method named id. <p>
142         *
143         * Returns the TypeSig for the innermost lexically enclosing type
144         * that has a method named id or null if no such type exists.<p>
145         *
146         * Note: inherited methods are considered to lexically enclose
147         * the code of their subclasses.<p>
148         *
149         * id disambiguates to C[.this].id.<p>
150         *
151         * This routine does not check that a resulting method
152         * is actually accessible. <p>
153         */
154        //@ ensures (this instanceof EnvForCU) ==> \result==null;
155        abstract public TypeSig locateMethod(/*@ non_null @*/ Identifier id);
156    
157    
158        /***************************************************
159         *                                                 *
160         * Debugging functions:                            *
161         *                                                 *
162         **************************************************/
163    
164        /**
165         * Display information about us to System.out.  This function is
166         * intended only for debugging use.
167         */
168        abstract public void display();
169    
170    
171        ///////////////////////////////////////////////////////////////////////
172        //                                                                   //
173        // Derived Methods                                                   //
174        //                                                                   //
175        ///////////////////////////////////////////////////////////////////////
176    
177    
178        /***************************************************
179         *                                                 *
180         * Type variable names:                            *
181         *                                                 *
182         **************************************************/
183    
184        /**
185         * Attempts to find the canonical prefix of a given name that
186         * denotes a TypeName in this environment. <p>
187         *
188         * A canonical prefix is composed of a base type name (either the
189         * leftmost identifer or a fully-quantified outside type name
190         * (P.I) depending), extended by some number of type member
191         * accesses (.C1.C2...).
192         *
193         * If ignoreFields is not set, then we stop extending the base
194         * type name as soon as we encounter an access that can refer to
195         * a field.  If it is set, then we stop extending only when we
196         * reach the end of the name or an access that cannot refer to a
197         * type member. <p>
198         *
199         * If we encounter an ambiguous prefix, we report a fatal error
200         * at loc via ErrorSet.<p>
201         *
202         * Otherwise, we return the TypeSig that the found prefix denotes
203         * (null if the prefix is of length 0) and sets prefixSize to the
204         * prefix's size. <p>
205         *
206         * This routine does not check that the resulting type (if any)
207         * is actually accessible, unless caller is not null. <p>
208         */
209        //@ modifies prefixSize;
210        //@ ensures \result==null ==> 0==prefixSize;
211        //@ ensures \result != null ==> 0<prefixSize && prefixSize <= n.length;
212        public TypeSig findTypeNamePrefix(TypeSig caller,
213                                          /*@ non_null @*/ Name n,
214                                          boolean ignoreFields) {
215            // Check for an unqualified name first:
216            TypeSig sig = lookupSimpleTypeName(caller,n.identifierAt(0),
217                                               n.getStartLoc());
218            prefixSize = 1;
219            if (sig==null) {
220                // Nope; must be a qualified name with a non-empty package prefix:
221                while (++prefixSize<=n.size()) {
222                    // Lookup n[0]..n[prefixSize-2] . n[prefixSize-1]:
223                    sig = OutsideEnv.lookup(n.prefix(prefixSize-1).toStrings(),
224                                    n.identifierAt(prefixSize-1).toString());
225                    if (sig != null)
226                        break;      // Stop at smallest qualified name
227                }
228                if (prefixSize>n.size()) {
229                    prefixSize = 0;
230                    return null;
231                }
232            }
233    
234            // Here we have that n[0]..n[prefixSize-1] denotes the type sig
235    
236            // Try and extend it as much as possible via nested types
237            while (prefixSize<n.size()) {
238                Identifier id = n.identifierAt(prefixSize);
239                int idLoc = n.locIdAt(prefixSize);
240    
241                // Stop if next access refers to a field & !ignoreFields:
242                if (!ignoreFields && sig.hasField(id))
243                    break;
244    
245                // Stop if next access cannot refer to a type member:
246                TypeSig next = sig.lookupType(caller, id, idLoc);
247                if (next==null)
248                    break;
249    
250                sig = next;
251                prefixSize++;
252            }
253    
254            return sig;
255        }
256        //* Holds the second return value of findTypeNamePrefix
257        public int prefixSize;
258    
259    
260        /**
261         * Attempt to lookup a TypeName using this environment. <p>
262         *
263         * If it encounters an ambiguous prefix, a fatal error is
264         * reported via ErrorSet.<p>
265         *
266         * Otherwise, returns the TypeSig that n denotes or null if n
267         * does not denote a type.<p>
268         *
269         * This routine does not check that the resulting type (if any)
270         * is actually accessible, unless caller is not null. <p>
271         */
272        public TypeSig lookupTypeName(TypeSig caller, /*@ non_null @*/ Name n) {
273            TypeSig sig = findTypeNamePrefix(caller, n, true);
274            if (prefixSize != n.size())
275                return null;
276    
277            return sig;
278        }
279    
280    
281        /**
282         * This processes the annotations on a type name
283         */
284        //@ ensures \result != null;
285        public TypeSig processTypeNameAnnotations(/*@ non_null @*/ TypeName n, 
286                                                  /*@ non_null @*/ TypeSig sig) {
287            return PrepTypeDeclaration.inst.processTypeNameAnnotations(n,sig,this);
288        }
289        
290    
291        /**
292         * Attempt to resolve a TypeName using this environment. <p>
293         *
294         * If an error occurs (including no such type), reports it to
295         * ErrorSet via a fatal error.<p>
296         *
297         * Otherwise, returns the TypeSig that n denotes.  This TypeSig
298         * may also later be obtained by using TypeSig.getSig on n.<p>
299         *
300         * This routine does not check that the resulting type (if any)
301         * is actually accessible, unless caller is not null. <p>
302         */
303        //@ ensures \result != null;
304        public TypeSig resolveTypeName(TypeSig caller, /*@ non_null @*/ TypeName tn) {
305            Name n = tn.name;
306    
307            TypeSig sig = TypeSig.getRawSig(tn);  // FIXME - use caller ?
308            if (sig != null)
309                return sig;
310    
311            sig = lookupTypeName(caller, n);
312            if (sig==null) {
313                ErrorSet.fatal(tn.name.locIdAt(0),
314                               "Can't find type named \""
315                               + tn.name.printName() + "\"");
316            }
317    
318            sig = processTypeNameAnnotations(tn, sig);  // FIXME - use caller?
319            TypeSig.setSig(tn, sig);
320            return sig;
321        }
322    
323        /**
324         * decoration holding the type environment in which a type is resolved.
325         */
326        //@ invariant typeEnv != null;
327        //@ invariant typeEnv.decorationType == \type(Env);
328        static public ASTDecoration typeEnv = 
329            new ASTDecoration("environment");
330    
331        /**
332         * Attempt to resolve a Type using this environment. <p>
333         *
334         * If an error occurs, reports it to ErrorSet via a fatal error.<p>
335         *
336         * This routine does not check that (immediate) types (if any)
337         * are actually accessible, if caller is null. <p>
338         */
339        public void resolveType(TypeSig caller, /*@ non_null @*/ Type t) {
340            typeEnv.set(t,this);
341            switch(t.getTag()) {
342              case TagConstants.ARRAYTYPE:
343                resolveType(caller, ((ArrayType)t).elemType);
344                break;
345    
346              case TagConstants.TYPENAME:
347                resolveTypeName(caller, (TypeName)t);
348                break;
349    
350              // No need to resolve primitive types or TypeSigs...
351            }
352        }
353    
354    
355        /***************************************************
356         *                                                 *
357         * Expr names:                                     *
358         *                                                 *
359         **************************************************/
360    
361        /**
362         * Attempt to disambiguate an Expr Name.  Either returns the
363         * disambiguated Name as an Expr or null if it does not denote
364         * anything. <p>
365         *
366         * If non-null, the result will always be a field access of some
367         * kind.
368         *
369         * If a prefix of n is ambiguous because of multiple
370         * import-on-demand declarations, a fatal error will result.
371         * Nothing is reported if n does not name anything.<p>
372         *
373         *
374         * If n is a reference to a field f in lexically enclosing class
375         * C, then the result will be of the form "[C.]this.n" if C's
376         * instance fields are accessible and "C.n" otherwise.<p>
377         *
378         * (At this point we haven't decided which field f refers to so
379         * we don't know if it is an instance field or not.)
380         */
381        //@ ensures !(\result instanceof AmbiguousVariableAccess);
382        public Expr disambiguateExprName(/*@ non_null @*/ Name n) {
383            /*
384             * Find the smallest prefix of n, n[0]..n[prefix-1], such that
385             * it denotes an Expr, call it left:
386             */
387            Expr left = null;
388            Identifier leftmost = n.identifierAt(0);
389            int leftmostLoc = n.getStartLoc();
390    
391            ASTNode result = locateFieldOrLocal(leftmost);
392            int prefix = 1;
393            if (result instanceof GenericVarDecl) {
394                // leftmost is a local variable:
395                left = VariableAccess.make(leftmost, leftmostLoc,
396                                           (GenericVarDecl)result);
397            } else if (result instanceof TypeSig) {
398                // leftmost is a field in class result:
399                ObjectDesignator od = getObjectDesignator((TypeSig)result,
400                                                          leftmostLoc);
401                left = FieldAccess.make(od, leftmost, leftmostLoc);
402            } else {
403                // n *must* start with a typename then:
404                TypeSig sig = findTypeNamePrefix(null, n, false); // FIXME - a caller for access checking?
405                if (sig==null || prefixSize==n.size())
406                    return null;
407    
408                prefix = prefixSize+1;
409                TypeName tn = TypeName.make(n.prefix(prefixSize));
410                TypeSig.setSig(tn, sig);
411                int leftmostDot = leftmostLoc;
412                if (prefixSize>0)
413                    leftmostDot = n.locDotAfter(prefixSize-1);
414                ObjectDesignator od =
415                    TypeObjectDesignator.make(leftmostDot, tn);
416                left = FieldAccess.make(od, n.identifierAt(prefixSize),
417                                        n.locIdAt(prefixSize));
418            }
419    
420    
421            /*
422             * Extend the prefix to the full n by using field dereferences:
423             */
424            for (; prefix<n.size(); prefix++) {
425                left = FieldAccess.make(
426                                ExprObjectDesignator.make(n.locDotAfter(prefix-1),
427                                                          left),
428                                n.identifierAt(prefix),
429                                n.locIdAt(prefix));
430            }
431    
432            return left;
433        }
434    
435        public Object disambiguateTypeOrFieldName(/*@ non_null */ Name n) {
436            /*
437             * Find the smallest prefix of n, n[0]..n[prefix-1], such that
438             * it denotes an Expr, call it left:
439             */
440            Expr left = null;
441            Identifier leftmost = n.identifierAt(0);
442            int leftmostLoc = n.getStartLoc();
443    
444            ASTNode result = locateFieldOrLocal(leftmost);
445            int prefix = 1;
446            if (result instanceof GenericVarDecl) {
447                // leftmost is a local variable:
448                left = VariableAccess.make(leftmost, leftmostLoc,
449                                           (GenericVarDecl)result);
450            } else if (result instanceof TypeSig) {
451                // leftmost is a field in class result:
452                ObjectDesignator od = getObjectDesignator((TypeSig)result,
453                                                          leftmostLoc);
454                left = FieldAccess.make(od, leftmost, leftmostLoc);
455            } else {
456                // n *must* start with a typename then:
457                TypeSig sig = findTypeNamePrefix(null, n, false); // FIXME - a caller for access checking?
458                if (sig==null) return null;
459                if (prefixSize==n.size()) return sig;
460    
461                prefix = prefixSize+1;
462                TypeName tn = TypeName.make(n.prefix(prefixSize));
463                TypeSig.setSig(tn, sig);
464                int leftmostDot = leftmostLoc;
465                if (prefixSize>0)
466                    leftmostDot = n.locDotAfter(prefixSize-1);
467                ObjectDesignator od =
468                    TypeObjectDesignator.make(leftmostDot, tn);
469                left = FieldAccess.make(od, n.identifierAt(prefixSize),
470                                        n.locIdAt(prefixSize));
471            }
472    
473    
474            /*
475             * Extend the prefix to the full n by using field dereferences:
476             */
477            for (; prefix<n.size(); prefix++) {
478                left = FieldAccess.make(
479                                ExprObjectDesignator.make(n.locDotAfter(prefix-1),
480                                                          left),
481                                n.identifierAt(prefix),
482                                n.locIdAt(prefix));
483            }
484    
485            return left;
486        }
487    
488    
489        /***************************************************
490         *                                                 *
491         * Routine names:                                  *
492         *                                                 *
493         **************************************************/
494    
495        /**
496         * Attempt to disambiguate an AmbiguousMethodInvocation.  Either
497         * returns the disambiguated method invocation as an Expr or
498         * reports a fatal error to ErrorSet if it does not denote
499         * anything.<p>
500         *
501         * The result will always be a method invocation.<p>
502         *
503         * If a prefix of n is ambiguous because of multiple
504         * import-on-demand declarations, a fatal error will result.
505         *
506         *
507         * If n is a reference to a method m in lexically enclosing class
508         * C, then the result will be of the form "[C.]this.m" if C's
509         * instance methods are accessible and "C.m" otherwise.<p>
510         *
511         * (At this point we haven't decided which method m refers to so
512         * we don't know if it is an instance method or not.)
513         */
514        public MethodInvocation disambiguateMethodName(
515                                    /*@ non_null @*/ AmbiguousMethodInvocation inv) {
516            ObjectDesignator where;     // Where the method comes from
517            
518            Name n = inv.name;
519            int size = n.size();
520            int nStart = n.getStartLoc();
521    
522    
523            /*
524             * Handle the simple name case first:
525             */
526            if (n.size()==1) {
527                Identifier id = n.identifierAt(0);
528                TypeSig container = locateMethod(id);
529                if (container==null)
530                    ErrorSet.fatal(nStart,
531                                   "No method named " + id + " is in scope here.");
532                
533                where = getObjectDesignator(container, nStart);
534            } else {
535                /*
536                 * Not a simple name; try preceeding name as an ExprName first:
537                 */
538                Name butRight = n.prefix(size-1);
539                Expr e = disambiguateExprName(butRight);
540                if (e != null)
541                    where = ExprObjectDesignator.make(n.locDotAfter(size-2), e);
542                else {
543                    /*
544                     * then try preceeding name as a TypeName:
545                     */
546                    TypeSig t = lookupTypeName(null,butRight); // FIXME - a caller for access checking?
547                    if (t != null) {
548                        TypeName tn = TypeName.make(butRight);
549                        TypeSig.setSig(tn, t);
550                        where = TypeObjectDesignator.make(n.locDotAfter(size-2),
551                                                          tn);
552                    } else {
553                        /*
554                         * Give up!
555                         */
556                        ErrorSet.fatal(nStart,
557                            "Can't disambiguate method name " + n.printName());
558                        where = null;     // keep compiler happy
559                    }
560                }
561            }
562    
563    
564            // Return <where>.rightmost(...):
565            Identifier rightmost = n.identifierAt(size-1);
566            int rightmostLoc = n.locIdAt(size-1);
567            return MethodInvocation.make(where, rightmost, null, rightmostLoc,
568                                         inv.locOpenParen, inv.args);
569        }
570    
571    
572        /***************************************************
573         *                                                 *
574         * Current/enclosing instances II:                 *
575         *                                                 *
576         **************************************************/
577    
578        /**
579         * Returns the innermost current or enclosing instance, or null
580         * if none exists.
581         */
582        public TypeSig getInnermostInstance() {
583            if (!isStaticContext())
584                return getEnclosingClass();
585            else
586                return getEnclosingInstance();
587        }
588    
589    
590        /**
591         * Are C's instance variables accessible? <p>
592         *
593         * If C is getEnclosingClass(), then this is equivalent to
594         * isStaticContext().
595         */
596        public boolean canAccessInstance(/*@ non_null @*/ TypeSig C) {
597            /*
598             * C's instance variables are accessible iff C is one of our
599             * current or enclosing instances:
600             */
601            for (TypeSig instance = getInnermostInstance();
602                 instance != null;
603                 instance = instance.getEnv(true).getEnclosingInstance()) {
604                if (instance==C)
605                    return true;
606            }
607    
608            return false;
609        }
610    
611    
612        /**
613         * Attempt to locate a current or enclosing instance that has
614         * type T. <p>
615         *
616         * If such exist, return an inferred "<actual class>.this" Expr
617         * for the innermost such one; otherwise, return null.  The
618         * location fields of the Expr will be set to loc.<p>
619         *
620         * Note: The returned instance may have be of a subtype of T.<p>
621         */
622        //@ requires loc != Location.NULL;
623        public Expr lookupEnclosingInstance(/*@ non_null @*/ TypeSig T,
624                                            int loc) {
625            TypeSig instance;
626    
627            // Find innermost satisfactory instance if it exists:
628            for (instance = getInnermostInstance();
629                 instance != null;
630                 instance = instance.getEnv(true).getEnclosingInstance()) {
631                if (instance.isSubtypeOf(T))
632                    break;
633            }
634    
635            if (instance==null)
636                return null;
637           
638            return getInferredThisExpr(instance, loc);
639        }
640    
641    
642        /***************************************************
643         *                                                 *
644         * Finding where something is declared:            *
645         *                                                 *
646         **************************************************/
647    
648        /**
649         * Decorates LocalVarDecl and FormalParaDecl nodes to point to
650         * the TypeSig of the type they are declared in. <p>
651         *
652         * Set by the EnvForLocals constructor.<p>
653         */
654        //@ invariant whereDecoration.decorationType == \type(TypeSig);
655        protected static final ASTDecoration whereDecoration
656            = new ASTDecoration("whereDecoration");
657    
658    
659        /**
660         * What type is a GenericVarDecl declared in? <p>
661         *
662         * Precondition: decl's type has been "parsed"; an Env containing
663         * decl has been constructed.<p>
664         */
665        //@ requires (decl instanceof FieldDecl) ==> ((FieldDecl)decl).hasParent;
666        //@ ensures \result != null;
667        public static TypeSig whereDeclared(/*@ non_null @*/ GenericVarDecl decl) {
668            TypeSig result;
669    
670            if (decl instanceof FieldDecl) {
671                TypeDecl parent = ((FieldDecl)decl).getParent();
672                Assert.notNull(parent);
673                result = TypeSig.getSig(parent);
674            } else {
675                // LocalVarDecl or FormalParaDecl left here:
676                result = (TypeSig)whereDecoration.get(decl);
677            }
678    
679            Assert.notNull(result);          //@ nowarn Pre;
680            return result;
681        }
682    
683    
684        /***************************************************
685         *                                                 *
686         * Expr-construction utility functions:            *
687         *                                                 *
688         **************************************************/
689    
690        /**
691         * Return an inferred ThisExpr for "[C.]this", using location loc. <p>
692         *
693         * The "C." part is omitted if C is the type of this (e.g.,
694         * getEnclosingClass()).
695         */
696        //@ requires loc != Location.NULL;
697        //@ ensures \result != null;
698        public final ThisExpr getInferredThisExpr(/*@ non_null @*/ TypeSig C,
699                                                  int loc) {
700            ThisExpr newThis = ThisExpr.make((C == getEnclosingClass())
701                                             ? null : C, loc);
702            newThis.inferred = true;
703    
704            return newThis;
705        }
706    
707    
708        /**
709         * Return an inferred ObjectDesignator for use in a reference to
710         * a possibly-instance member of class C from here. <p>
711         *
712         *
713         * If C's instance variables are not accessible from this point
714         * (see canAccessInstance(-)), then returns "C.". <p>
715         *
716         * Otherwise returns an inferred "[C.]this.".
717         * (cf. getInferredThisExpr(-))
718         *
719         * loc is used as the location for the this. and C. parts.
720         */
721        //@ requires loc != Location.NULL;
722        //@ ensures \result != null;
723        public final ObjectDesignator getObjectDesignator(/*@ non_null @*/ TypeSig C,
724                                                          int loc) {
725            if (!canAccessInstance(C))
726                return TypeObjectDesignator.make(loc, C);
727            else
728                return ExprObjectDesignator.make(loc,
729                                                 getInferredThisExpr(C, loc));
730        }
731    }