📄 typecheck.jrag
字号:
// 15.15.1 public void PreIncExpr.typeCheck() { if(!getOperand().isVariable()) error("prefix increment expression only work on variables"); else if(!getOperand().type().isNumericType()) error("unary increment only operates on numeric types"); } // 15.15.2 public void PreDecExpr.typeCheck() { if(!getOperand().isVariable()) error("prefix decrement expression only work on variables"); else if(!getOperand().type().isNumericType()) error("unary decrement only operates on numeric types"); } public void IfStmt.typeCheck() { TypeDecl cond = getCondition().type(); if(!cond.isBoolean()) { error("the type of \"" + getCondition() + "\" is " + cond.name() + " which is not boolean"); } } public void WhileStmt.typeCheck() { TypeDecl cond = getCondition().type(); if(!cond.isBoolean()) { error("the type of \"" + getCondition() + "\" is " + cond.name() + " which is not boolean"); } } public void DoStmt.typeCheck() { TypeDecl cond = getCondition().type(); if(!cond.isBoolean()) { error("the type of \"" + getCondition() + "\" is " + cond.name() + " which is not boolean"); } } public void ForStmt.typeCheck() { if(hasCondition()) { TypeDecl cond = getCondition().type(); if(!cond.isBoolean()) { error("the type of \"" + getCondition() + "\" is " + cond.name() + " which is not boolean"); } } } public void SwitchStmt.typeCheck() { TypeDecl type = getExpr().type(); if(!type.isIntegralType() || type.isLong()) error("Switch expression must be of char, byte, short, or int"); } public void ConstCase.typeCheck() { TypeDecl switchType = switchType(); TypeDecl type = getValue().type(); if(!type.assignConversionTo(switchType, getValue())) error("Constant expression must be assignable to Expression"); if(!getValue().isConstant() && !getValue().type().isUnknown()) error("Switch expression must be constant"); } inh TypeDecl Case.switchType(); eq SwitchStmt.getBlock().switchType() = getExpr().type(); eq Program.getChild().switchType() = unknownType(); public void SynchronizedStmt.typeCheck() { TypeDecl type = getExpr().type(); if(!type.isReferenceType() || type.isNull()) error("*** The type of the expression must be a reference"); } public void CatchClause.typeCheck() { if(!getParameter().type().instanceOf(typeThrowable())) error("*** The catch variable must extend Throwable"); } public void ThrowStmt.typeCheck() { if(!getExpr().type().instanceOf(typeThrowable())) error("*** The thrown expression must extend Throwable"); } public void AssertStmt.typeCheck() { // 14.10 if(!getfirst().type().isBoolean()) error("Assert requires boolean condition"); if(hasExpr() && getExpr().type().isVoid()) error("The second part of an assert statement may not be void"); } public void MethodDecl.typeCheck() { // Thrown vs super class method see MethodDecl.nameCheck // 8.4.4 TypeDecl exceptionType = typeThrowable(); for(int i = 0; i < getNumException(); i++) { TypeDecl typeDecl = getException(i).type(); if(!typeDecl.instanceOf(exceptionType)) error(signature() + " throws non throwable type " + typeDecl.fullName()); } // check returns if(!isVoid() && hasBlock() && getBlock().canCompleteNormally()) error("the body of a non void method may not complete normally"); } // 14.16 inh TypeDecl TypeDecl.typeVoid(); inh TypeDecl ReturnStmt.returnType(); eq TypeDecl.getBodyDecl().returnType() = typeVoid(); eq MethodDecl.getBlock().returnType() = type(); eq Program.getChild().returnType() = typeVoid(); public void ReturnStmt.typeCheck() { if(hasResult() && !returnType().isVoid()) { if(!getResult().type().assignConversionTo(returnType(), getResult())) error("return value must be an instance of " + returnType().typeName() + " which " + getResult().type().typeName() + " is not"); } // 8.4.5 8.8.5 if(returnType().isVoid() && hasResult()) error("return stmt may not have an expression in void methods"); // 8.4.5 if(!returnType().isVoid() && !hasResult()) error("return stmt must have an expression in non void methods"); if(enclosingBodyDecl() instanceof InstanceInitializer || enclosingBodyDecl() instanceof StaticInitializer) error("Initializers may not return"); } public void ConstructorDecl.typeCheck() { // 8.8.4 (8.4.4) TypeDecl exceptionType = typeThrowable(); for(int i = 0; i < getNumException(); i++) { TypeDecl typeDecl = getException(i).type(); if(!typeDecl.instanceOf(exceptionType)) error(signature() + " throws non throwable type " + typeDecl.fullName()); } } public void ClassInstanceExpr.typeCheck() { if(isQualified() && qualifier().isTypeAccess() && !qualifier().type().isUnknown()) error("*** The expression in a qualified class instance expr must not be a type name"); // 15.9 if(isQualified() && !type().isInnerClass() && !((ClassDecl)type()).superclass().isInnerClass() && !type().isUnknown()) { error("*** Qualified class instance creation can only instantiate inner classes and their anonymous subclasses"); } if(!type().isClassDecl()) { error("*** Can only instantiate classes, which " + type().typeName() + " is not"); } typeCheckEnclosingInstance(); typeCheckAnonymousSuperclassEnclosingInstance(); } public void ClassInstanceExpr.typeCheckEnclosingInstance() { TypeDecl C = type(); if(!C.isInnerClass()) return; TypeDecl enclosing = null; if(C.isAnonymous()) { if(noEnclosingInstance()) { enclosing = null; } else { enclosing = hostType(); } } else if(C.isLocalClass()) { if(C.inStaticContext()) { enclosing = null; } else if(noEnclosingInstance()) { enclosing = unknownType(); } else { TypeDecl nest = hostType(); while(nest != null && !nest.instanceOf(C.enclosingType())) nest = nest.enclosingType(); enclosing = nest; } } else if(C.isMemberType()) { if(!isQualified()) { if(noEnclosingInstance()) { error("No enclosing instance to initialize " + C.typeName() + " with"); //System.err.println("ClassInstanceExpr: Non qualified MemberType " + C.typeName() + " is in a static context when instantiated in " + this); enclosing = unknownType(); } else { TypeDecl nest = hostType(); while(nest != null && !nest.instanceOf(C.enclosingType())) nest = nest.enclosingType(); enclosing = nest == null ? unknownType() : nest; } } else { enclosing = enclosingInstance(); } } if(enclosing != null && !enclosing.instanceOf(type().enclosingType())) { String msg = enclosing == null ? "None" : enclosing.typeName(); error("*** Can not instantiate " + type().typeName() + " with the enclosing instance " + msg + " due to incorrect enclosing instance"); } else if(!isQualified() && C.isMemberType() && inExplicitConstructorInvocation() && enclosing == hostType()) { error("*** The innermost enclosing instance of type " + enclosing.typeName() + " is this which is not yet initialized here."); } } inh TypeDecl SuperConstructorAccess.enclosingInstance(); inh TypeDecl ClassInstanceExpr.enclosingInstance(); inh TypeDecl TypeDecl.enclosingInstance(); eq Program.getChild().enclosingInstance() = null; eq StaticInitializer.getBlock().enclosingInstance() = null; //eq InstanceInitializer.getBlock().enclosingInstance() = null; eq TypeDecl.getBodyDecl().enclosingInstance() { if(getBodyDecl(childIndex) instanceof MemberTypeDecl && !((MemberTypeDecl)getBodyDecl(childIndex)).typeDecl().isInnerType()) return null; if(getBodyDecl(childIndex) instanceof ConstructorDecl) return enclosingInstance(); return this; } eq AbstractDot.getRight().enclosingInstance() = getLeft().type(); eq ConstructorDecl.getConstructorInvocation().enclosingInstance() = unknownType(); syn boolean ClassInstanceExpr.noEnclosingInstance() = isQualified() ? qualifier().staticContextQualifier() : inStaticContext(); public void ClassInstanceExpr.typeCheckAnonymousSuperclassEnclosingInstance() { if(type().isAnonymous() && ((ClassDecl)type()).superclass().isInnerType()) { TypeDecl S = ((ClassDecl)type()).superclass(); if(S.isLocalClass()) { if(S.inStaticContext()) { } else if(noEnclosingInstance()) { error("*** No enclosing instance to class " + type().typeName() + " due to static context"); } else if(inExplicitConstructorInvocation()) error("*** No enclosing instance to superclass " + S.typeName() + " of " + type().typeName() + " since this is not initialized yet"); } else if(S.isMemberType()) { if(!isQualified()) { // 15.9.2 2nd paragraph if(noEnclosingInstance()) { error("*** No enclosing instance to class " + type().typeName() + " due to static context"); } else { TypeDecl nest = hostType(); while(nest != null && !nest.instanceOf(S.enclosingType())) nest = nest.enclosingType(); if(nest == null) { error("*** No enclosing instance to superclass " + S.typeName() + " of " + type().typeName()); } else if(inExplicitConstructorInvocation()) { error("*** No enclosing instance to superclass " + S.typeName() + " of " + type().typeName() + " since this is not initialized yet"); } } } } } } public void ArrayTypeWithSizeAccess.typeCheck() { super.typeCheck(); if(!getExpr().type().unaryNumericPromotion().isInt()) error(getExpr().type().typeName() + " is not int after unary numeric promotion"); } // 15.25 public void ConditionalExpr.typeCheck() { if(!getCondition().type().isBoolean()) error("*** First expression must be a boolean in conditional operator"); if(type().isUnknown() && !getTrueExpr().type().isUnknown() && !getFalseExpr().type().isUnknown()) { error("*** Operands in conditional operator does not match"); } } public void IntegerLiteral.typeCheck() { if(constant().error) error("The value of an int literal must be a decimal value in the range -2147483648..2147483647 or a hexadecimal or octal literal that fits in 32 bits."); } public void LongLiteral.typeCheck() { if(constant().error) error("The value of the long literal " + getLITERAL() + " is not legal"); } public void FloatingPointLiteral.typeCheck() { if(!isZero() && constant().floatValue() == 0.0f) error("It is an error for nonzero floating-point " + getLITERAL() + " to round to zero"); if(constant().floatValue() == Float.NEGATIVE_INFINITY || constant().floatValue() == Float.POSITIVE_INFINITY) error("It is an error for floating-point " + getLITERAL() + " to round to an infinity"); } public void DoubleLiteral.typeCheck() { if(!isZero() && constant().doubleValue() == 0.0f) error("It is an error for nonzero floating-point " + getLITERAL() + " to round to zero"); if(constant().doubleValue() == Double.NEGATIVE_INFINITY || constant().doubleValue() == Double.POSITIVE_INFINITY) error("It is an error for floating-point " + getLITERAL() + " to round to an infinity"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -