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