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 }