Esempio n. 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;
    }
  }