Пример #1
0
  /**
   * Type-checks this method declaration. It first checks that if this method overrides a method of
   * a superclass then the return type is a subtype of that of the overridden method. Then it builds
   * a type-checker whose only variable in scope is {@code this} of type {@code clazz} and the
   * parameters of the method, and where return instructions of type {@code returnType} are allowed.
   * It then type-checks the body of the method in that type-checker. It finally checks that if this
   * method does not return {@code void}, then every execution path ends with a {@code return}
   * command.
   *
   * @param clazz the semantical type of the class where this method occurs
   */
  @Override
  protected void typeCheckAux(ClassType clazz) {
    TypeChecker checker;
    ClassType superclass;
    MethodSignature overridden;
    Type rt = returnType.typeCheck();

    // we build a type-checker which signals errors for the source code
    // of the class where this method is defined,
    // whose only variables in scope is this of type
    // clazz and the parameters of the method, and
    // where return instructions of type returnType are allowed
    checker = new TypeChecker(rt, clazz.getErrorMsg());

    // the main method is the only <i>static</i> method, where there is no this variable
    if (!getSignature().getName().equals("main")) checker = checker.putVar("this", clazz);

    // we enrich the type-checker with the formal parameters
    checker = getFormals() != null ? getFormals().typeCheck(checker) : checker;

    TypeList pars = getFormals() != null ? getFormals().typeCheck() : null;

    // we check if this method overrides a method of some superclass
    superclass = clazz.getSuperclass();
    if (superclass != null) {
      overridden = superclass.methodLookup(name, pars);

      if (overridden != null)
        // it does override a method of a superclass. We check
        // that its return type has been refined. We use the
        // canBeAssignedToSpecial method so that
        // void can be overridden into void
        if (!rt.canBeAssignedToSpecial(overridden.getReturnType()))
          error(
              checker,
              "illegal return type for overriding method \""
                  + name
                  + "\". Was "
                  + overridden.getReturnType());
    }

    // we type-check the body of the method in the resulting type-checker
    getBody().typeCheck(checker);

    // we check that there is no dead-code in the body of the method
    boolean stopping = getBody().checkForDeadcode();

    // we check that if the method does not return void then
    // every syntactical execution path in the method ends with
    // a return command (continue and break are forbidden in this position)
    if (rt != VoidType.INSTANCE && !stopping) error(checker, "missing return statement");
  }
Пример #2
0
 /**
  * Generates the Java bytecode corresponding to this Kitten bytecode.
  *
  * @param classGen the Java class generator to be used for this generation
  * @return the Java {@code checkcast intoType} bytecode for casts between reference types and a
  *     type conversion bytecode such as {@code i2f} for conversions between numercial types
  */
 @Override
 public InstructionList generateJavaBytecode(AbstractClassGenerator classGen) {
   if (intoType instanceof ReferenceType)
     // we use the instruction factory to simplify the addition of the type to the constant pool
     return new InstructionList(
         classGen
             .getFactory()
             .createCheckCast((org.apache.bcel.generic.ReferenceType) intoType.toBCEL()));
   else if (fromType == IntType.INSTANCE && intoType == FloatType.INSTANCE)
     return new InstructionList(new I2F());
   else // it must be float into int
   return new InstructionList(new F2I());
 }