예제 #1
0
  /**
   * Create an instantiation of a generic prototype given by parameter gt
   *
   * @param gt
   * @param env
   * @return
   */
  private CompilationUnit createGenericPrototypeInstantiation(
      ExprGenericPrototypeInstantiation gt, Env env) {

    CompilationUnit genericProto = null;

    /* if ( gt.getName().equals("generic02.gb.G1<X>") ) {
    	System.out.println("generic02.gb.G1<X>");
    	gt.ifPrototypeReturnsNameWithPackageAndType(env);
    } */

    String genSourceFileName = gt.getGenericSourceFileName();

    String genSourceFileNameVaryingNumberOfParameters =
        gt.getGenericSourceFileNameWithVaryingNumberOfParameters();
    // if ( gt.getRealTypeListList().size() > 1 )
    // System.out.println("3");

    boolean isInterface = false;
    if (NameServer.isPrototypeFromInterface(genSourceFileName)) {
      // int sizePrefix = NameServer.prefixProtoInterface.length();
      isInterface = true;
      /*
      genSourceFileName = genSourceFileName.substring(sizePrefix);
      genSourceFileNameVaryingNumberOfParameters = genSourceFileNameVaryingNumberOfParameters.substring(sizePrefix);
      */
      genSourceFileName = NameServer.prototypeFileNameFromInterfaceFileName(genSourceFileName);
      genSourceFileNameVaryingNumberOfParameters =
          NameServer.prototypeFileNameFromInterfaceFileName(
              genSourceFileNameVaryingNumberOfParameters);
    }
    // something like util.Stack if gt is "util.Stack<Int>" or
    // Stack if gt is Stack<Int>
    ExprIdentStar typeIdent = gt.getTypeIdent();
    if (typeIdent.getIdentSymbolArray().size() == 1) {
      // no package preceding the generic prototype name as in "Stack<Int>"
      ProgramUnit pu =
          env.searchProgramUnitBySourceFileName(genSourceFileName, gt.getFirstSymbol(), false);
      if (pu != null) {
        genericProto = pu.getCompilationUnit();
        ProgramUnit pu2 =
            env.searchProgramUnitBySourceFileName(
                genSourceFileNameVaryingNumberOfParameters, gt.getFirstSymbol(), false);
        if (pu2 != null)
          /* found both generic prototype and generic prototype with varying number of parameters
           * Example: found both Tuple<T> and Tuple<T+>
           */
          env.error(
              gt.getFirstSymbol(),
              "Ambiguity in creating a real prototype from a generic prototype. There is both "
                  + pu.getCompilationUnit().getPackageName()
                  + "."
                  + genSourceFileName
                  + " and "
                  + pu2.getCompilationUnit().getPackageName()
                  + "."
                  + genSourceFileNameVaryingNumberOfParameters,
              true);
      }
      if (genericProto == null) {
        pu =
            env.searchProgramUnitBySourceFileName(
                genSourceFileNameVaryingNumberOfParameters, gt.getFirstSymbol(), false);
        if (pu != null) genericProto = pu.getCompilationUnit();
      }
    } else {
      // package preceding the generic prototype name as in "util.Stack<Int>"
      int i = 0;
      ArrayList<Symbol> symbolList = typeIdent.getIdentSymbolArray();
      int sizeLessOne = symbolList.size() - 1;
      String packageName = "";
      while (i < sizeLessOne) {
        packageName = packageName + symbolList.get(i).getSymbolString();
        ++i;
        if (i < sizeLessOne) packageName += ".";
      }
      CyanPackage cyanPackage = env.getProject().searchPackage(packageName);
      if (cyanPackage == null) {
        env.error(typeIdent.getFirstSymbol(), "Package '" + packageName + "' was not found", true);
        return null;
      }
      // first searches for something like "Stack(1)" in package 'util'
      for (CompilationUnit cunit : cyanPackage.getCompilationUnitList()) {
        if (genSourceFileName.equals(cunit.getFileNameWithoutExtension())) {
          genericProto = cunit;
          break;
        }
      }
      CompilationUnit genericProto2 = null;
      // searches for a generic prototype with varying number of parameters
      // something like "Stack(1+)"
      for (CompilationUnit cunit : cyanPackage.getCompilationUnitList()) {
        if (genSourceFileNameVaryingNumberOfParameters.equals(
            cunit.getFileNameWithoutExtension())) {
          genericProto2 = cunit;
          break;
        }
      }

      if (genericProto != null && genericProto2 != null) {
        env.error(
            gt.getFirstSymbol(),
            "Ambiguity in creating a real prototype from a generic prototype. There is both "
                + genericProto.getPackageName()
                + "."
                + genSourceFileName
                + " and "
                + genericProto2.getPackageName()
                + "."
                + genSourceFileNameVaryingNumberOfParameters,
            true);
      }
      if (genericProto == null) genericProto = genericProto2;
    }

    // genericProto = nameGenProtoUnitTable.get(genSourceFileName);

    if (genericProto == null) {
      env.error(
          true,
          gt.getFirstSymbol(),
          "Prototype '" + gt.getName() + "' was not found",
          gt.getName(),
          ErrorKind.prototype_was_not_found_inside_method);
      /*gt.getProgramUnit().getCompilationUnit().error(null,
      "Internal error at CompilerManager::createInterfaceObjectFunctionAndArray: cannot create " + gt.getName()); */
      return null;
    } else {
      /**
       * if there was no compilation error in "Stack(1).cyan", then create an instance of the
       * generic prototype
       */
      if (isInterface) {
        gt.removeProtoPrefix();
      }

      CompilationUnit newCompilationUnit = genericProto.createInstanceGenericPrototype(gt, env);
      CompilationUnit interCompilationUnit = null;
      /**
       * if the package for this generic prototype instantiation was not created before, create it
       * now.
       */
      CyanPackage cyanPackage = genericProto.getCyanPackage();

      cyanPackage.addCompilationUnit(newCompilationUnit);
      newCompilationUnit.setCyanPackage(cyanPackage);
      nonGenericCompilationUnitList.add(newCompilationUnit);

      if (nameSet.contains(newCompilationUnit.getFullFileNamePath())) {
        env.error(gt.getFirstSymbol(), "Internal error in CompilerManager");
        gt.ifPrototypeReturnsNameWithPackageAndType(env);
      } else nameSet.add(newCompilationUnit.getFullFileNamePath());

      program.addCompilationUnit(newCompilationUnit);

      newCompilationUnit.readSourceFile();
      HashSet<saci.CompilationInstruction> compInstSet = new HashSet<>();
      compInstSet.add(CompilationInstruction.dpa_actions);
      compInstSet.add(CompilationInstruction.pp_addCode);
      if (compilationStep.compareTo(CompilationStep.step_5) >= 0)
        compInstSet.add(CompilationInstruction.new_addCode);
      Compiler compiler =
          new Compiler(newCompilationUnit, compInstSet, compilationStep, project, null);
      compiler.parse();

      if (newCompilationUnit.hasCompilationError()) {
        // newCompilationUnit.printErrorList(printWriter);
        env.setThereWasError(true);
        throw new CompileErrorException();
      } else if (compInstSet.contains(CompilationInstruction.createPrototypesForInterfaces)
          && newCompilationUnit.getPrototypeIsNotGeneric()
          && newCompilationUnit.getPublicPrototype() instanceof InterfaceDec) {
        // if public program unit is an interface, create ProtoInterface

        interCompilationUnit = newCompilationUnit.createProtoInterface();
        if (interCompilationUnit != null) {

          interCompilationUnit.setCyanPackage(cyanPackage);
          cyanPackage.addCompilationUnit(interCompilationUnit);
          newCompilationUnit.setCyanPackage(cyanPackage);
          nonGenericCompilationUnitList.add(interCompilationUnit);

          String nameInter = interCompilationUnit.getFilename();
          if (nameInter.endsWith(NameServer.dotCyanSourceFileExtension))
            nameInter =
                nameInter.substring(
                    0, nameInter.length() - NameServer.sizeCyanSourceFileExtensionPlusOne);

          // nameRealGenProtoUnitTable.put(nameInter, interCompilationUnit);
          program.addCompilationUnit(interCompilationUnit);

          interCompilationUnit.readSourceFile();
          compiler =
              new Compiler(interCompilationUnit, compInstSet, compilationStep, project, null);
          compiler.parse();
          if (interCompilationUnit.getActionList().size() > 0)
            interCompilationUnit.doActionList(printWriter);
          interCompilationUnit.clearErrorsActions();
        }
      }
      // newCompilationUnit.clearErrorsActions();
      if (isInterface) return interCompilationUnit;
      else return newCompilationUnit;
    }
  }
예제 #2
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();
    }
  }