Example #1
0
  /**
   * Create a generic prototype from parameter gpi. The new prototype is compiled. If it is an
   * interface, the prototype Proto_IntefaceName is created too. Methods calcInterfaceTypes and
   * calcInternalTypes are called for both the prototype and its Proto_InterfaceName, if any.
   *
   * @param gpi
   * @param env
   * @return
   */
  public static ProgramUnit createGenericPrototype(ExprGenericPrototypeInstantiation gpi, Env env) {

    saci.Tuple<String, Type> t = gpi.ifPrototypeReturnsNameWithPackageAndType(env);

    // t.f1 is the name of the prototype
    if (t != null && t.f2 != null) {
      /*
       * prototype has already been created before
       */
      if (t.f2 instanceof ProgramUnit) {
        return (ProgramUnit) t.f2;
      } else {
        env.error(
            gpi.getFirstSymbol(),
            "Internal error: a type that is not a program unit is used to instantiate a generic prototype");
        return null;
      }

    } else {
      /*
       * prototype has not been created. Create it.
       */
      // if ( env.getCurrentMethod() != null && env.getCurrentMethod().getName().contains("run2") )
      //	gpi.ifPrototypeReturnsItsNameWithPackage(env);

      /*
       * first, create all prototypes that are real parameters to this generic prototype instantiation
       */
      for (ArrayList<Expr> realTypeList : gpi.getRealTypeListList()) {
        for (Expr realType : realTypeList) {
          if (realType instanceof ExprGenericPrototypeInstantiation) {
            ExprGenericPrototypeInstantiation genRealType =
                (ExprGenericPrototypeInstantiation) realType;
            genRealType.setType(createGenericPrototype(genRealType, env));
            // 		javaName = type.getJavaName();
            genRealType.setJavaName(genRealType.getType().getJavaName());
          }
        }
      }

      CompilationUnit compUnit =
          env.getProject().getCompilerManager().createGenericPrototypeInstantiation(gpi, env);

      Env newEnv = new Env(env.getProject());
      /*
      * If a generic prototype is created when method calcInterfaceTypes of Program is being executed
      * (env.getProject().getProgram().getInCalcInterfaceTypes() returns true), it is not necessary
      * to call its method calcInterfaceTypes. It will be called in the loop of
      * method Program::calcInterfaceTypes.

      * If a generic prototype is created when method calcInternalTypes of Program is being executed,
      * method calcInterfaceTypes of this generic prototype should be called because the interface
      * of this prototype is necessary in methods calcInternalTypes. Method calcInternalTypes
      * of this newly created generic prototype will be called in the loop of
      * method Program::calcInternalTypes.
      *
      * calcInternalTypes cannot be called when a generic prototype is created when
      * the compiler is calling calcInterfaceTypes. If this is allowed, some calcInternalType
      * method could try to use the interface of some prototype P whose method calcInterfaceTypes
      * have not been called.
      */
      if (!env.getProject().getProgram().getInCalcInterfaceTypes()) {
        compUnit.calcInterfaceTypes(newEnv);
        // compUnit.calcInternalTypes(newEnv);
      }
      CompilationUnit interfaceCompilationUnit = compUnit.getInterfaceCompilationUnit();
      if (interfaceCompilationUnit != null) {
        newEnv = new Env(env.getProject());
        if (!env.getProject().getProgram().getInCalcInterfaceTypes()) {
          interfaceCompilationUnit.calcInterfaceTypes(newEnv);
        }
      }
      /*
       * if the generic prototype was created from phase (4), included, onwards, then execute
       * the ati actions. A generic prototype instantiation can only change itself and
       * no other prototype can change it.
       */
      if (env.getProject().getCompilerManager().getCompilationStep().ordinal()
          > CompilationStep.step_3.ordinal()) {
        apply_ati_ActionsToGenericPrototype(newEnv, compUnit);
        if (interfaceCompilationUnit != null) {
          apply_ati_ActionsToGenericPrototype(env, interfaceCompilationUnit);
        }
      }

      return compUnit.getPublicPrototype();
    }
  }