001 /* 002 * JastAddJ is covered by the modified BSD License. You should have received a copy of the 003 * modified BSD license with this compiler. 004 * 005 * Copyright (c) 2011, Jesper Öqvist <jesper.oqvist@cs.lth.se> 006 * All rights reserved. 007 */ 008 009 /** 010 * <p>This aspect adds the Project Coin/JSR 334 Strings in Switch language change 011 * to the JastAddJ frontend. 012 * 013 * <p>The following features were modified: 014 * <ul> 015 * <li>type checking of the switch expression</li> 016 * <li>duplicate checking of switch labels</li> 017 * </ul> 018 */ 019 aspect StringsInSwitch { 020 /** 021 * <p>Overrides the type checking of the switch statement's expression. 022 * 023 * <p>In JSR 334 a switch statement may use an expression of type String. 024 */ 025 refine Enums public void SwitchStmt.typeCheck() { 026 TypeDecl type = getExpr().type(); 027 if ((!type.isIntegralType() || type.isLong()) && !type.isEnumDecl() 028 && !type.isString()) 029 error("Switch expression must be of type " + 030 "char, byte, short, int, enum, or string"); 031 } 032 033 /* Type checking for case labels need not be changed as it 034 * already tests if the case labels have expressions which are 035 * assignable to the switch expression 036 */ 037 038 syn boolean Case.isDefaultCase() = false; 039 eq DefaultCase.isDefaultCase() = true; 040 041 /** 042 * <p>This attribute overrides the default duplicate checking for 043 * switch case labels. 044 */ 045 refine Enums eq ConstCase.constValue(Case c) { 046 if (isDefaultCase() || c.isDefaultCase()) 047 return isDefaultCase() && c.isDefaultCase(); 048 049 Expr myValue = getValue(); 050 Expr otherValue = ((ConstCase) c).getValue(); 051 TypeDecl myType = myValue.type(); 052 TypeDecl otherType = otherValue.type(); 053 if (myType.isString() || otherType.isString()) { 054 if (!myType.isString() || !otherType.isString()) 055 return false; 056 if (!myValue.isConstant() || !otherValue.isConstant()) 057 return false; 058 return myValue.constant().stringValue().equals( 059 otherValue.constant().stringValue()); 060 } 061 062 return refined(c); 063 } 064 065 /** 066 * <p>Improve the type checking error messages given for case labels. 067 */ 068 refine Enums public void ConstCase.typeCheck() { 069 boolean isEnumConstant = getValue().isEnumConstant(); 070 TypeDecl switchType = switchType(); 071 TypeDecl type = getValue().type(); 072 if (switchType.isEnumDecl() && !isEnumConstant) 073 error("Unqualified enumeration constant required"); 074 if (!type.assignConversionTo(switchType, getValue())) 075 error("Case label has incompatible type "+switchType.name()+ 076 ", expected type compatible with "+type.name()); 077 if (!getValue().isConstant() && !getValue().type().isUnknown() && 078 !isEnumConstant) 079 error("Case label must have constant expression"); 080 } 081 082 }