📄 typecheck.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. */aspect TypeCheck { public void ASTNode.typeCheck() { } syn boolean Expr.isVariable() = false; eq AbstractDot.isVariable() = lastAccess().isVariable(); eq VarAccess.isVariable() = true; eq ArrayAccess.isVariable() = true; eq ParExpr.isVariable() = getExpr().isVariable(); // 5.2 public void VariableDeclaration.typeCheck() { if(hasInit()) { TypeDecl source = getInit().type(); TypeDecl dest = type(); if(!source.assignConversionTo(dest, getInit())) error("can not assign " + name() + " of type " + dest.typeName() + " a value of type " + source.typeName()); } } // 5.2 public void FieldDeclaration.typeCheck() { if(hasInit()) { TypeDecl source = getInit().type(); TypeDecl dest = type(); if(!source.assignConversionTo(dest, getInit())) error("can not assign " + name() + " of type " + dest.typeName() + " a value of type " + source.typeName()); } } // 5.2 Assignment Conversion public void AssignSimpleExpr.typeCheck() { if(!getDest().isVariable()) error("left hand side is not a variable"); else if(!sourceType().assignConversionTo(getDest().type(), getSource()) && !sourceType().isUnknown()) error("can not assign " + getDest() + " of type " + getDest().type().typeName() + " a value of type " + sourceType().typeName()); } public void AssignExpr.typeCheck() { if(!getDest().isVariable()) error("left hand side is not a variable"); else { TypeDecl source = sourceType(); TypeDecl dest = getDest().type(); if(getSource().type().isPrimitive() && getDest().type().isPrimitive()) return; error("can not assign " + getDest() + " of type " + getDest().type().typeName() + " a value of type " + sourceType().typeName()); } } public void AssignMultiplicativeExpr.typeCheck() { if(sourceType().isBoolean() || getDest().type().isBoolean()) error("Multiplicative operators do not operate on boolean types"); super.typeCheck(); } public void AssignPlusExpr.typeCheck() { if(!getDest().isVariable()) error("left hand side is not a variable"); else if(getSource().type().isUnknown() || getDest().type().isUnknown()) return; else if(getDest().type().isString() && !(getSource().type().isVoid())) return; else if(getSource().type().isBoolean() || getDest().type().isBoolean()) error("Operator + does not operate on boolean types"); else if(getSource().type().isPrimitive() && getDest().type().isPrimitive()) return; else error("can not assign " + getDest() + " of type " + getDest().type().typeName() + " a value of type " + sourceType().typeName()); } public void AssignMinusExpr.typeCheck() { if(sourceType().isBoolean() || getDest().type().isBoolean()) error("Operator - does not operate on boolean types"); super.typeCheck(); } public void AssignShiftExpr.typeCheck() { if(!sourceType().isIntegralType() || !getDest().type().isIntegralType()) error("Shift operators only operate on integral types"); super.typeCheck(); } public void AssignBitwiseExpr.typeCheck() { TypeDecl source = sourceType(); TypeDecl dest = getDest().type(); if(source.isIntegralType() && dest.isIntegralType()) super.typeCheck(); else if(source.isBoolean() && dest.isBoolean()) super.typeCheck(); else error("Operator only operates on integral and boolean types"); } syn TypeDecl AssignExpr.sourceType() = getSource().type().isPrimitive() ? getSource().type() : unknownType(); eq AssignPlusExpr.sourceType() { TypeDecl left = getDest().type(); TypeDecl right = getSource().type(); if(!left.isString() && !right.isString()) return super.sourceType(); if(left.isVoid() || right.isVoid()) return unknownType(); return left.isString() ? left : right; } syn TypeDecl AssignSimpleExpr.sourceType() = getSource().type(); // 5.3 Method Invocation Conversion public void MethodAccess.typeCheck() { for(int i = 0; i < decl().getNumParameter(); i++) { TypeDecl exprType = getArg(i).type(); TypeDecl parmType = decl().getParameter(i).type(); if(!exprType.methodInvocationConversionTo(parmType) && !exprType.isUnknown() && !parmType.isUnknown()) { error("The type " + exprType.typeName() + " of expr " + getArg(i) + " is not compatible with the method parameter " + decl().getParameter(i)); } } } // 15.13 public void ArrayAccess.typeCheck() { if(isQualified() && !qualifier().type().isArrayDecl() && !qualifier().type().isUnknown()) error("the type " + qualifier().type().name() + " of the indexed element is not an array"); if(!getExpr().type().unaryNumericPromotion().isInt() || !getExpr().type().isIntegralType()) error("array index must be int after unary numeric promotion which " + getExpr().type().typeName() + " is not"); } public void ArrayInit.typeCheck() { TypeDecl initializerType = declType().componentType(); if(initializerType.isUnknown()) error("the dimension of the initializer is larger than the expected dimension"); for(int i = 0; i < getNumInit(); i++) { Expr e = getInit(i); if(!e.type().assignConversionTo(initializerType, e)) error("the type " + e.type().name() + " of the initializer is not compatible with " + initializerType.name()); } } // 15.17 public void MultiplicativeExpr.typeCheck() { if(!getLeftOperand().type().isNumericType()) error(getLeftOperand().type().typeName() + " is not numeric"); if(!getRightOperand().type().isNumericType()) error(getRightOperand().type().typeName() + " is not numeric"); } // 15.18 public void AdditiveExpr.typeCheck() { if(!getLeftOperand().type().isNumericType()) error(getLeftOperand().type().typeName() + " is not numeric"); if(!getRightOperand().type().isNumericType()) error(getRightOperand().type().typeName() + " is not numeric"); } // 15.18 public void AddExpr.typeCheck() { TypeDecl left = getLeftOperand().type(); TypeDecl right = getRightOperand().type(); if(!left.isString() && !right.isString()) super.typeCheck(); else if(left.isVoid()) error("The type void of the left hand side is not numeric"); else if(right.isVoid()) error("The type void of the right hand side is not numeric"); } // 15.19 public void ShiftExpr.typeCheck() { if(!getLeftOperand().type().isIntegralType()) error(getLeftOperand().type().typeName() + " is not integral"); if(!getRightOperand().type().isIntegralType()) error(getRightOperand().type().typeName() + " is not integral"); } // 15.22 public void BitwiseExpr.typeCheck() { TypeDecl left = getLeftOperand().type(); TypeDecl right = getRightOperand().type(); if(left.isIntegralType() && right.isIntegralType()) return; else if(left.isBoolean() && right.isBoolean()) return; else error(left.typeName() + " is not compatible with " + right.typeName()); } // 15.20 public void RelationalExpr.typeCheck() { if(!getLeftOperand().type().isNumericType()) error(getLeftOperand().type().typeName() + " is not numeric"); if(!getRightOperand().type().isNumericType()) error(getRightOperand().type().typeName() + " is not numeric"); } // 15.23, 15.24 public void LogicalExpr.typeCheck() { if(!getLeftOperand().type().isBoolean()) error(getLeftOperand().type().typeName() + " is not boolean"); if(!getRightOperand().type().isBoolean()) error(getRightOperand().type().typeName() + " is not boolean"); } // 15.21 public void EqualityExpr.typeCheck() { TypeDecl left = getLeftOperand().type(); TypeDecl right = getRightOperand().type(); if(left.isNumericType() && right.isNumericType()) return; else if(left.isBoolean() && right.isBoolean()) return; else if((left.isReferenceType() || left.isNull()) && (right.isReferenceType() || right.isNull())) { if(left.castingConversionTo(right) || right.castingConversionTo(left)) return; } error(left.typeName() + " can not be compared to " + right.typeName()); } // 15.20.2 public void InstanceOfExpr.typeCheck() { TypeDecl relationalExpr = getExpr().type(); TypeDecl referenceType = getTypeAccess().type(); if(!relationalExpr.isUnknown()) { if(!relationalExpr.isReferenceType() && !relationalExpr.isNull()) error("The relational expression in instance of must be reference or null type"); if(!referenceType.isReferenceType()) error("The reference expression in instance of must be reference type"); if(!relationalExpr.castingConversionTo(referenceType)) error("The type " + relationalExpr.typeName() + " of the relational expression " + getExpr() + " can not be cast into the type " + referenceType.typeName()); if(getExpr().isTypeAccess()) error("The relational expression " + getExpr() + " must not be a type name"); } } // 15.16 public void CastExpr.typeCheck() { TypeDecl expr = getExpr().type(); TypeDecl type = getTypeAccess().type(); if(!expr.isUnknown()) { if(!expr.castingConversionTo(type)) error(expr.typeName() + " can not be cast into " + type.typeName()); if(!getTypeAccess().isTypeAccess()) error("" + getTypeAccess() + " is not a type access in cast expression"); } } public void ParExpr.typeCheck() { if(getExpr().isTypeAccess()) error("" + getExpr() + " is a type and may not be used in parenthesized expression"); } // 15.15.3 public void PlusExpr.typeCheck() { if(!getOperand().type().isNumericType()) error("unary plus only operates on numeric types"); } // 15.15.4 public void MinusExpr.typeCheck() { if(!getOperand().type().isNumericType()) error("unary minus only operates on numeric types"); } // 15.15.5 public void BitNotExpr.typeCheck() { if(!getOperand().type().isIntegralType()) error("unary ~ only operates on integral types"); } // 15.15.6 public void LogNotExpr.typeCheck() { if(!getOperand().type().isBoolean()) error("unary ! only operates on boolean types"); } // 15.14 public void PostfixExpr.typeCheck() { if(!getOperand().isVariable()) error("postfix expressions only work on variables"); else if(!getOperand().type().isNumericType()) error("postfix expressions only operates on numeric types"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -