001    aspect TypeAnalysis {
002      
003      
004      // ***API***
005      
006      // Declaration of *type*
007      // Refers to the appropriate type of the declaration or expression,
008      // or refers to unknownDecl if there is no appropriate type in the program.
009      syn lazy TypeDecl Decl.type();
010      syn lazy TypeDecl Exp.type();
011    
012      // Declaration of *isSubtypeOf*
013      // Compares two types
014      syn lazy boolean TypeDecl.isSubtypeOf(TypeDecl typeDecl);
015    
016      // Declaration of *isValue*
017      // True if the expression denotes a value, i.e., something that can be assigned to a variable.
018      syn boolean Exp.isValue();
019    
020      // *hasCycleOnSuperclassChain* - true if there is a cycle somewhere on the superclass chain
021      // Defined using a circular attribute.
022      syn lazy boolean ClassDecl.hasCycleOnSuperclassChain() circular [true];
023      
024      // *superClass* - the superclass declaration
025      // - if it exists and if there are no cycles on the superclass chain
026      // - otherwise null
027      syn lazy ClassDecl ClassDecl.superClass();
028      
029      
030      // ***Implementation***
031      
032      // Definition of *type*
033      eq TypeDecl.type() = this;
034      eq VarDecl.type() = getType().decl().type();
035    
036      eq IdUse.type() = decl().type();
037      eq Dot.type() = getIdUse().type();
038    
039      eq BooleanLiteral.type() = booleanType();
040    
041      // Definition of *isSubtypeOf*
042      // use double dispatch to allow modular extension of type comparisons
043      eq TypeDecl.isSubtypeOf(TypeDecl typeDecl) = typeDecl.isSuperTypeOf(this);
044      eq ClassDecl.isSubtypeOf(TypeDecl typeDecl) = typeDecl.isSuperTypeOfClassDecl(this);
045    
046      syn lazy boolean TypeDecl.isSuperTypeOf(TypeDecl typeDecl) = this == typeDecl;
047      syn lazy boolean TypeDecl.isSuperTypeOfClassDecl(ClassDecl typeDecl) = 
048        this == typeDecl || typeDecl.superClass() != null && typeDecl.superClass().isSubtypeOf(this);
049        
050      // Definition of *superClass*
051      eq ClassDecl.superClass() {
052        if (hasSuperclass() && getSuperclass().decl() instanceof ClassDecl && !hasCycleOnSuperclassChain())
053          return (ClassDecl) getSuperclass().decl();
054        else
055          return null;
056      }
057    
058      // *hasCycleOnSuperclassChain* - true if there is a cycle somewhere on the superclass chain
059      eq ClassDecl.hasCycleOnSuperclassChain() {
060        if (hasSuperclass() && getSuperclass().decl() instanceof ClassDecl) //First, check if there is a superclass
061          return ((ClassDecl) getSuperclass().decl()).hasCycleOnSuperclassChain();
062        else
063          return false;
064      }
065    
066      // Definition of *isValue*
067      eq Exp.isValue() = true;
068      eq Dot.isValue() = getIdUse().isValue();
069    
070      eq TypeUse.isValue() = false;
071      // Note! If we did not have the rewrites below, the above equation would have to instead be written as:
072      // eq IdUse.isValue() = !(decl() instanceof TypeDecl)
073    
074      // Rewrite rules for replacing Use-nodes based on their declaration kind
075      /*
076      rewrite Use {
077        when(decl() instanceof VarDecl) to VariableUse 
078        new VariableUse(getName());
079        
080      }
081      
082      rewrite Use {
083        when(decl() instanceof TypeDecl)
084        to TypeUse new TypeUse(getName());
085      }
086      */
087      
088      rewrite Use {
089        when(decl() instanceof VarDecl) to VariableUse {
090    
091                VariableUse use = new VariableUse(getName());           
092                return use;
093        }
094        
095      }
096      
097      rewrite Use {
098        when(decl() instanceof TypeDecl) to TypeUse {
099        
100               TypeUse use = new TypeUse(getName());           
101               return use;
102        }
103      }
104      
105    }