Package org.sugarj.driver

Source Code of org.sugarj.driver.ImportCommands

package org.sugarj.driver;

import java.io.IOException;
import java.text.ParseException;

import org.spoofax.interpreter.terms.IStrategoTerm;
import org.spoofax.jsglr.client.InvalidParseTableException;
import org.spoofax.jsglr.shared.BadTokenException;
import org.spoofax.jsglr.shared.SGLRException;
import org.spoofax.jsglr.shared.TokenExpectedException;
import org.strategoxt.lang.StrategoException;
import org.sugarj.AbstractBaseProcessor;
import org.sugarj.common.ATermCommands;
import org.sugarj.common.Environment;
import org.sugarj.common.FileCommands;
import org.sugarj.common.Log;
import org.sugarj.common.path.Path;
import org.sugarj.common.path.RelativePath;
import org.sugarj.util.Pair;

/**
* @author seba
*/
public class ImportCommands {
 
  private AbstractBaseProcessor baseProcessor;
  private Environment environment;
  private Driver driver;
  private Result driverResult;
  private STRCommands str;
 
  public ImportCommands(AbstractBaseProcessor baseProcessor, Environment environment, Driver driver, Result driverResult, STRCommands str) {
    this.baseProcessor = baseProcessor;
    this.environment = environment;
    this.driver = driver;
    this.driverResult = driverResult;
    this.str = str;
  }

  /**
   * Resolve module
   *
   * @param term
   * @param toplevelDecl
   * @param asModel If true, looks for models. If false, looks for transformations.
   * @return
   */
  private RelativePath resolveModule(IStrategoTerm term, IStrategoTerm toplevelDecl, boolean asModel) throws TokenExpectedException, IOException, ParseException, InvalidParseTableException, SGLRException, InterruptedException {
    if (ATermCommands.isApplication(term, "TransApp")) {
      IStrategoTerm model = ATermCommands.getApplicationSubterm(term, "TransApp", 1);
      IStrategoTerm transformation = ATermCommands.getApplicationSubterm(term, "TransApp", 0);
      Pair<String, Boolean> transformedModel = transformModel(model, transformation, toplevelDecl);
      if (transformedModel != null) {
        if (asModel)
          return ModuleSystemCommands.importModel(transformedModel.a, environment, driverResult);
        else
          return ModuleSystemCommands.importStratego(transformedModel.a, environment, driverResult);
      }
      return null;
    }
   
    String path = baseProcessor.getModulePath(term);
    if (path.contains("/")) {
      boolean isCircularImport = driver.prepareImport(toplevelDecl, path);
      if (isCircularImport)
        return null;
     
      if (asModel)
        return ModuleSystemCommands.importModel(path, environment, driverResult);
      else
        return ModuleSystemCommands.importStratego(path, environment, driverResult);
    }
   
    throw new RuntimeException("TODO support non-qualifed transformations and model paths");
    // TODO support non-qualifed transformations and model paths
   
//    return null;
  }

  /**
   * Transforms the given model with the given transformation.
   *
   * @param model AST part of the import that denotes the model.
   * @param transformation AST part of the import that denotes the transformation.
   * @param toplevelDecl
   * @param environment
   * @param driver
   * @return a pair consisting of the path to the transformed model and a flag indicating a circular import (if true).
   */
  public Pair<String, Boolean> transformModel(IStrategoTerm model, IStrategoTerm transformation, IStrategoTerm toplevelDecl) throws TokenExpectedException, IOException, ParseException, InvalidParseTableException, SGLRException, InterruptedException {
    RelativePath modelPath = resolveModule(model, toplevelDecl, true);
    RelativePath transformationPath = resolveModule(transformation, toplevelDecl, false);
   
    if (modelPath == null) {
      // something's wrong
      String name;
      try {
        name = baseProcessor.getModulePath(model);
      } catch (Exception e) {
        name = model.toString();
      }
      driver.setErrorMessage(toplevelDecl, "model not found " + name);
      return null;
    }
    if (transformationPath == null) {
      // something's wrong
      String name;
      try {
        name = baseProcessor.getModulePath(transformation);
      } catch (Exception e) {
        name = transformation.toString();
      }
      driver.setErrorMessage(toplevelDecl, "transformation not found " + name);
      return null;
    }

    Log.log.beginTask("Transform model " + FileCommands.fileName(modelPath) + " with transformation " + FileCommands.fileName(transformationPath), Log.TRANSFORM);
    try {
      RelativePath transformedModelSourceFile = getTransformedModelSourceFilePath(modelPath, transformationPath, environment);
      String transformedModelPath = FileCommands.dropExtension(transformedModelSourceFile.getRelativePath());
      Result transformedModelResult = ModuleSystemCommands.locateResult(transformedModelPath, environment);
 
      if (transformedModelResult != null && transformedModelResult.isUpToDate(environment)) {
        // result of transformation is already up-to-date, nothing to do here.
        driverResult.addDependency(transformedModelResult);
        return Pair.create(transformedModelPath, false);
      }
      else {
        // transform the model, prepare the import of the resulting code.
        IStrategoTerm transformedModel = executeTransformation(modelPath, transformationPath, toplevelDecl, environment, str, driver);
        String transformedModelText = ATermCommands.atermToString(transformedModel);
        driverResult.generateFile(transformedModelSourceFile, transformedModelText);
       
        boolean isCircularImport = driver.prepareImport(toplevelDecl, transformedModelPath);
        return Pair.create(transformedModelPath, isCircularImport);
      }
    } finally {
      Log.log.endTask();
    }
  }
 
  /**
   * Apply the transformation to the model and return the result.
   *
   * Assumes that the model and transformation are already registered as dependencies with the current driver result.
   *
   * @param model Path to the *.model file that contains the Aterm model.
   * @param transformationPath Path to the *.str transformation.
   */
  private static IStrategoTerm executeTransformation(RelativePath model, RelativePath transformationPath, IStrategoTerm toplevelDecl, Environment environment, STRCommands str, Driver driver) throws IOException, TokenExpectedException, BadTokenException, InvalidParseTableException, SGLRException {
    IStrategoTerm modelTerm = ATermCommands.atermFromFile(model.getAbsolutePath());
    String strat = "main-" + FileCommands.dropExtension(transformationPath.getRelativePath()).replace('/', '_');
    Result transformationResult = ModuleSystemCommands.locateResult(FileCommands.dropExtension(transformationPath.getRelativePath()), environment);
   
    Path trans = str.compile(transformationPath, strat, transformationResult.getTransitiveFileDependencies());
   
    IStrategoTerm transformationInput =
        ATermCommands.makeTuple(
            modelTerm,
            ATermCommands.makeString(FileCommands.dropExtension(model.getRelativePath()), null),
            ATermCommands.makeString(FileCommands.dropExtension(transformationPath.getRelativePath()), null));

    try {
      IStrategoTerm transformedTerm = str.assimilate(strat, trans, transformationInput);
      return transformedTerm;
    } catch (StrategoException e) {
      String msg = "Failed to apply transformation " + transformationPath.getRelativePath() + " to model " + model.getRelativePath() + ": " + e.getMessage();
      driver.setErrorMessage(toplevelDecl, msg);
      throw new StrategoException(msg);
    }
  }
 
  /**
   * Computes the path of the model file generated from the given model path by the given transformation path.
   *
   * @param modelPath
   * @param transformationPath
   * @param environment
   * @return
   */
  public static RelativePath getTransformedModelSourceFilePath(RelativePath modelPath, RelativePath transformationPath, Environment environment) {
    if (modelPath == null)
      return null;
    if (transformationPath == null)
      return environment.createOutPath(modelPath + ".model");
   
    String transformationPathString = FileCommands.dropExtension(transformationPath.getRelativePath());
    String transformedModelPath = FileCommands.dropExtension(modelPath.getRelativePath()) + "__" + transformationPathString.replace('/', '_');
    return environment.createOutPath(transformedModelPath + ".model");
  }
 
  /**
   * Retrieves the right-most model in the given transformation application and returns the model's name.
   *
   * @param appl
   * @param base processor
   * @return
   */
  public static String getTransformationApplicationModelPath(IStrategoTerm appl, AbstractBaseProcessor baseProcessor) {
    if (ATermCommands.isApplication(appl, "TransApp"))
      return getTransformationApplicationModelPath(appl.getSubterm(1), baseProcessor);
    return baseProcessor.getModulePath(appl);
  }
}
TOP

Related Classes of org.sugarj.driver.ImportCommands

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.