📄 typeanalysis.jrag
字号:
/* * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered * by the modified BSD License. You should have received a copy of the * modified BSD license with this compiler. * * Copyright (c) 2005-2008, Torbjorn Ekman * All rights reserved. */import java.util.*;// 5.1 Kinds of Conversionaspect TypeConversion { ///syn boolean TypeDecl.subtype(TypeDecl type) = instanceOf(type); // 5.1.1 Identity Conversion syn boolean TypeDecl.identityConversionTo(TypeDecl type) = this == type; syn boolean TypeDecl.wideningConversionTo(TypeDecl type) = instanceOf(type); syn lazy boolean TypeDecl.narrowingConversionTo(TypeDecl type) = instanceOf(type); // 5.1.2 Widening Primitive Conversions eq PrimitiveType.wideningConversionTo(TypeDecl type) = instanceOf(type); //eq IntType.wideningConversionTo(TypeDecl type) = type.isLong() || type.isFloat() || type.isDouble(); //eq FloatType.wideningConversionTo(TypeDecl type) = type.isLong(); // 5.1.3 Narrowing Primitive Conversion eq PrimitiveType.narrowingConversionTo(TypeDecl type) = type.instanceOf(this); eq ShortType.narrowingConversionTo(TypeDecl type) = type.isByte() || type.isChar(); eq CharType.narrowingConversionTo(TypeDecl type) = type.isByte() || type.isShort(); eq ByteType.narrowingConversionTo(TypeDecl type) = type.isChar(); // 5.1.4 Widening Reference Conversions eq ReferenceType.wideningConversionTo(TypeDecl type) = instanceOf(type); // 5.1.5 Narrowing Reference Conversions eq ReferenceType.narrowingConversionTo(TypeDecl type) { if(type.instanceOf(this)) return true; if(isClassDecl() && !getModifiers().isFinal() && type.isInterfaceDecl()) return true; if(isInterfaceDecl() && type.isClassDecl() && !type.getModifiers().isFinal()) return true; if(isInterfaceDecl() && type.instanceOf(this)) return true; if(fullName().equals("java.lang.Object") && type.isInterfaceDecl()) return true; // Dragons // TODO: Check if both are interfaces with compatible methods if(isArrayDecl() && type.isArrayDecl() && elementType().instanceOf(type.elementType())) return true; return false; } // 5.1.6 String Conversions syn boolean TypeDecl.stringConversion() = true; eq VoidType.stringConversion() = false; // 5.2 Assignment Conversion syn boolean TypeDecl.assignConversionTo(TypeDecl type, Expr expr) { //System.out.println("@@@ " + fullName() + " assign conversion to " + type.fullName() + ", expr: " + expr); boolean sourceIsConstant = expr != null ? expr.isConstant() : false; //System.out.println("@@@ sourceIsConstant: " + sourceIsConstant); if(identityConversionTo(type) || wideningConversionTo(type)) return true; //System.out.println("@@@ narrowing conversion needed"); //System.out.println("@@@ value: " + expr.value()); if(sourceIsConstant && (isInt() || isChar() || isShort() || isByte()) && (type.isByte() || type.isShort() || type.isChar()) && narrowingConversionTo(type) && expr.representableIn(type)) return true; //System.out.println("@@@ false"); return false; } // 5.3 Method Invocation Conversion syn lazy boolean TypeDecl.methodInvocationConversionTo(TypeDecl type) { return identityConversionTo(type) || wideningConversionTo(type); } // 5.5 Casting Conversion syn lazy boolean TypeDecl.castingConversionTo(TypeDecl type) = identityConversionTo(type) || wideningConversionTo(type) || narrowingConversionTo(type); eq ClassDecl.castingConversionTo(TypeDecl type) { if(type.isArrayDecl()) { return isObject(); } else if(type.isClassDecl()) { return this == type || instanceOf(type) || type.instanceOf(this); } else if(type.isInterfaceDecl()) { return !isFinal() || instanceOf(type); } else return super.castingConversionTo(type); } inh MethodDecl InterfaceDecl.unknownMethod(); eq InterfaceDecl.castingConversionTo(TypeDecl type) { if(type.isArrayDecl()) { return type.instanceOf(this); } else if(type.isClassDecl()) { return !type.isFinal() || type.instanceOf(this); } else if(type.isInterfaceDecl()) { for(Iterator i1 = methodsIterator(); i1.hasNext(); ) { MethodDecl m = (MethodDecl)i1.next(); for(Iterator iter = type.methodsSignature(m.signature()).iterator(); iter.hasNext(); ) { MethodDecl n = (MethodDecl)iter.next(); if(n.type() != m.type()) return false; } } return true; } else return super.castingConversionTo(type); } eq ArrayDecl.castingConversionTo(TypeDecl type) { if(type.isArrayDecl()) { TypeDecl SC = componentType(); TypeDecl TC = type.componentType(); if(SC.isPrimitiveType() && TC.isPrimitiveType() && SC == TC) return true; if(SC.isReferenceType() && TC.isReferenceType()) { return SC.castingConversionTo(TC); } return false; } else if(type.isClassDecl()) { return type.isObject(); } else if(type.isInterfaceDecl()) { return type == typeSerializable() || type == typeCloneable(); } else return super.castingConversionTo(type); } inh TypeDecl ArrayDecl.typeSerializable(); inh TypeDecl ArrayDecl.typeCloneable(); }aspect NumericPromotion { syn TypeDecl TypeDecl.unaryNumericPromotion() = this; // not unknown since this would be // 5.6.1 Unary Numeric Promotion syn lazy TypeDecl NumericType.unaryNumericPromotion() = this; eq ByteType.unaryNumericPromotion() = typeInt(); eq ShortType.unaryNumericPromotion() = typeInt(); eq CharType.unaryNumericPromotion() = typeInt(); // 5.6.2 Binary Numeric Promotion syn TypeDecl TypeDecl.binaryNumericPromotion(TypeDecl type) = unknownType(); syn lazy TypeDecl NumericType.binaryNumericPromotion(TypeDecl type) { if(!type.isNumericType()) return unknownType(); return unaryNumericPromotion().instanceOf(type) ? type : unaryNumericPromotion(); }}aspect TypeAnalysis { // 4.1 The Kinds of Types and Values syn boolean TypeDecl.isReferenceType() = false; eq ReferenceType.isReferenceType() = true; eq UnknownType.isReferenceType() = true; syn boolean TypeDecl.isPrimitiveType() = false; eq PrimitiveType.isPrimitiveType() = true; eq UnknownType.isPrimitiveType() = true; // 4.2 Primitive Types and Values syn boolean TypeDecl.isNumericType() = false; eq NumericType.isNumericType() = true; eq UnknownType.isNumericType() = true; syn boolean TypeDecl.isIntegralType() = false; eq IntegralType.isIntegralType() = true; eq UnknownType.isIntegralType() = true; syn boolean TypeDecl.isBoolean() = false; eq BooleanType.isBoolean() = true; eq UnknownType.isBoolean() = true; syn boolean TypeDecl.isByte() = false; eq ByteType.isByte() = true; syn boolean TypeDecl.isChar() = false; eq CharType.isChar() = true; syn boolean TypeDecl.isShort() = false; eq ShortType.isShort() = true; syn boolean TypeDecl.isInt() = false; eq IntType.isInt() = true; eq UnknownType.isInt() = true; syn boolean TypeDecl.isFloat() = false; eq FloatType.isFloat() = true; syn boolean TypeDecl.isLong() = false; eq LongType.isLong() = true; syn boolean TypeDecl.isDouble() = false; eq DoubleType.isDouble() = true; syn boolean TypeDecl.isVoid() = false; eq VoidType.isVoid() = true; syn boolean TypeDecl.isNull() = false; eq NullType.isNull() = true; // 4.3 Reference Types and Values syn boolean TypeDecl.isClassDecl() = false; eq ClassDecl.isClassDecl() = true; syn boolean TypeDecl.isInterfaceDecl() = false; eq InterfaceDecl.isInterfaceDecl() = true; syn boolean TypeDecl.isArrayDecl() = false; eq ArrayDecl.isArrayDecl() = true; inh lazy boolean TypeDecl.isAnonymous(); eq ClassInstanceExpr.getTypeDecl().isAnonymous() = true; eq TypeDecl.getBodyDecl().isAnonymous() = false; eq Program.getChild().isAnonymous() = false; syn boolean TypeDecl.isPrimitive() = false; eq PrimitiveType.isPrimitive() = true; syn lazy boolean TypeDecl.isString() = false; eq ClassDecl.isString() = fullName().equals("java.lang.String"); syn lazy boolean TypeDecl.isObject() = false; eq ClassDecl.isObject() = name().equals("Object") && packageName().equals("java.lang"); syn boolean TypeDecl.isUnknown() = false; eq UnknownType.isUnknown() = true; eq Program.getChild().unknownField() = unknownType().findSingleVariable("unknown"); public FieldDeclaration TypeDecl.findSingleVariable(String name) { return (FieldDeclaration)memberFields(name).iterator().next(); } eq Program.getChild().unknownMethod() { for(Iterator iter = unknownType().memberMethods("unknown").iterator(); iter.hasNext(); ) { MethodDecl m = (MethodDecl)iter.next(); return m; } throw new Error("Could not find method unknown in type Unknown"); } eq Program.getChild().unknownConstructor() = unknownConstructor(); syn lazy ConstructorDecl Program.unknownConstructor() { return (ConstructorDecl)unknownType().constructors().iterator().next(); } eq AbstractDot.type() = lastAccess().type(); syn TypeDecl FieldDeclaration.type() = getTypeAccess().type(); syn TypeDecl VariableDeclaration.type() = getTypeAccess().type(); syn lazy TypeDecl ParameterDeclaration.type() = getTypeAccess().type(); inh lazy TypeDecl ArrayInit.declType(); eq Program.getChild(int i).declType() = null; eq FieldDecl.getVariableDecl().declType() = null; eq VarDeclStmt.getVariableDecl().declType() = null; eq FieldDeclaration.getInit().declType() = type(); eq VariableDeclaration.getInit().declType() = type(); eq ArrayCreationExpr.getArrayInit().declType() = type(); eq ArrayInit.getInit().declType() = declType().componentType(); eq ArrayInit.type() = declType(); inh TypeDecl ConstructorDecl.unknownType(); syn TypeDecl ConstructorDecl.type() = unknownType(); syn lazy TypeDecl MethodDecl.type() = getTypeAccess().type(); syn boolean BodyDecl.isVoid() = false; eq MethodDecl.isVoid() = type().isVoid(); eq FieldDeclaration.isVoid() = type().isVoid(); eq ConstructorDecl.isVoid() = true; syn lazy TypeDecl Expr.type(); eq Access.type() = unknownType(); eq TypeAccess.type() = decl(); eq ArrayAccess.type() = isQualified() ? qualifier().type().componentType() : unknownType(); inh TypeDecl ArrayAccess.unknownType(); eq VarAccess.type() = decl().type(); eq MethodAccess.type() = decl().type(); eq ConstructorAccess.type() = decl().type(); eq ThisAccess.type() = decl(); eq SuperAccess.type() { TypeDecl typeDecl = decl(); if(!typeDecl.isClassDecl()) return unknownType(); ClassDecl classDecl = (ClassDecl)typeDecl; if(!classDecl.hasSuperclass()) return unknownType(); return classDecl.superclass(); } eq AssignExpr.type() = getDest().type(); eq IntegerLiteral.type() = typeInt(); eq LongLiteral.type() = typeLong(); eq FloatingPointLiteral.type() = typeFloat(); eq DoubleLiteral.type() = typeDouble(); eq BooleanLiteral.type() = typeBoolean(); eq CharacterLiteral.type() = typeChar(); eq StringLiteral.type() = typeString(); eq NullLiteral.type() = typeNull(); eq ParExpr.type() = getExpr().isTypeAccess() ? unknownType() : getExpr().type(); eq ClassInstanceExpr.type() = hasTypeDecl() ? getTypeDecl() : getAccess().type(); eq ArrayCreationExpr.type() = getTypeAccess().type(); eq Unary.type() = getOperand().type(); eq PlusExpr.type() = getOperand().type().unaryNumericPromotion(); eq MinusExpr.type() = getOperand().type().unaryNumericPromotion(); eq BitNotExpr.type() = getOperand().type().unaryNumericPromotion(); eq LogNotExpr.type() = typeBoolean(); eq CastExpr.type() = getTypeAccess().type(); // 15.17 eq MultiplicativeExpr.type() = getLeftOperand().type().binaryNumericPromotion(getRightOperand().type()); // 15.18 eq AdditiveExpr.type() = getLeftOperand().type().binaryNumericPromotion(getRightOperand().type()); // 15.18 eq AddExpr.type() { TypeDecl left = getLeftOperand().type(); TypeDecl right = getRightOperand().type(); if(!left.isString() && !right.isString()) return super.type(); else { if(left.isVoid() || right.isVoid()) return unknownType(); // pick the string type return left.isString() ? left : right; } } // 15.19 eq ShiftExpr.type() = getLeftOperand().type().unaryNumericPromotion(); // 15.20, 15.21 eq RelationalExpr.type() = typeBoolean(); // 15.23, 15.24 eq LogicalExpr.type() = typeBoolean(); // 15.22 eq BitwiseExpr.type() { if(getLeftOperand().type().isIntegralType() && getRightOperand().type().isIntegralType()) // 15.22.1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -