Package frege.imp.parser

Source Code of frege.imp.parser.FregeParseController$FregeData

package frege.imp.parser;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.imp.builder.MarkerCreatorWithBatching;
import org.eclipse.imp.builder.ProblemLimit.LimitExceededException;
import org.eclipse.imp.model.ISourceProject;
import org.eclipse.imp.parser.IMessageHandler;
import org.eclipse.imp.parser.IParseController;
import org.eclipse.imp.parser.IParser;
import org.eclipse.imp.parser.ISourcePositionLocator;
import org.eclipse.imp.parser.ParseControllerBase;
import org.eclipse.imp.parser.SimpleAnnotationTypeInfo;
import org.eclipse.imp.preferences.IPreferencesService;
import org.eclipse.imp.services.IAnnotationTypeInfo;
import org.eclipse.imp.services.ILanguageSyntaxProperties;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.source.LineRange;

import frege.FregePlugin;
import frege.runtime.Delayed;
import frege.runtime.Fun1;
import frege.runtime.Lambda;
import frege.runtime.Lazy;
import frege.prelude.PreludeBase;
import frege.prelude.PreludeBase.TList.DCons;
import frege.prelude.PreludeBase.TTuple2;
import frege.prelude.PreludeBase.TList;
import frege.prelude.PreludeBase.TTuple3;
import frege.control.monad.State.TState;
import frege.control.monad.State.TStateT;
import frege.prelude.PreludeList;
import frege.prelude.PreludeList.IListView__lbrack_rbrack;
import frege.compiler.enums.Flags.TFlag;
import frege.compiler.enums.Flags.IEnum_Flag;
import frege.compiler.types.Global.TGlobal;
import frege.compiler.types.Global.TMessage;
import frege.compiler.types.Global.TOptions;
import frege.compiler.types.Positions.TPosition;
import frege.compiler.types.Global.TSeverity;
import frege.compiler.types.Global.TSubSt;
import frege.compiler.types.Tokens.TToken;
import frege.compiler.common.CompilerOptions;
import frege.ide.Utilities;
import frege.compiler.Main;
import frege.imp.builders.FregeBuilder;
import frege.imp.preferences.FregePreferencesConstants;
import frege.data.Bits.TBitSet;
import frege.data.TreeMap.TTree;


/**
* NOTE:  This version of the Parse Controller is for use when the Parse
* Controller and corresponding Node Locator are generated separately from
* a corresponding set of LPG grammar templates and possibly in the absence
* of the lexer, parser, and AST-related types that would be generated from
* those templates.  It is assumed that either a) the Controller will be
* used with a suitable set of lexer, parser, and AST-related types
* that are provided by some means other than LPG, or b) the Controller will
* be used with a set of lexer, parser, and AST types that have been, or will
* be, separately generated based on LPG.  In order to enable this version of
* the Parse Controller to compile, dummy lexer, parser, and AST-related types
* have been included as member types in the Controller.  These types are not
* operational and are merely placeholders for types that would support a
* functioning implementation.  Apart from the inclusion of these dummy types,
* this representation of the Parse Controller is the same as that used
* with LPG.
*  
* @author Stan Sutton (suttons@us.ibm.com)
* @since May 1,  2007  Addition of marker types
* @since May 10, 2007  Conversion IProject -> ISourceProject
* @since May 15, 2007  Addition of dummy types
*/
public class FregeParseController extends ParseControllerBase implements
    IParseController {

  public static class TokensIterator implements Iterator<TToken> {
    /** current token array */
    final private TToken[] toks;
    private IRegion region;
    private int  inx;
   
    /** check if token is within region */
    public static boolean within(TToken tok, IRegion region) {
      return (TToken.offset(tok) + TToken.value(tok).length() >= region.getOffset()
          && TToken.offset(tok) <= region.getOffset() + region.getLength());
    }
   
    /** construct an Iterator */
    public TokensIterator(TToken[] it, IRegion reg) {
      toks = it;
      region = reg;
      inx = 0;
      while (inx < toks.length) {
        TToken t = toks[inx];
        if (within(t, reg)) break;
        inx++;
      }
    }
   
    /*
    public static int skipBraces(final Array toks, int j) {
      while (j < toks.length()) {
        TToken tok = Delayed.<TToken>forced(toks.getAt(j));
        if (tok.mem$tokid == TTokenID.CHAR
            && (tok.mem$value.charAt(0) == '{'
                || tok.mem$value.charAt(0) == '}'
                || tok.mem$value.charAt(0) == ';')) {
          j++;
        }
        else if (tok.mem$tokid == TTokenID.PURE
            && !tok.mem$value.equals("pure")) {
          j++;
        }
        else break;
      }
      return j;
    }
    */
   
    @Override
    public boolean hasNext() {
      // skip { ; }
      // inx = skipBraces(toks, inx);
      // we have a next if we are not the empty list and the token is in the region
      return inx < toks.length
          && within(toks[inx], region);
    }
   
    @Override
    public TToken next() {
      // give back next token
      if (inx < toks.length) {
        return toks[inx++];
      }
      return null;
    }
   
    @Override
    public void remove() {
      throw new UnsupportedOperationException("TokensIterator");
    }   
  }
 
  public static class FregeData {
    private String sp = ".";
    private String fp = ".";
    private String bp = ".";
    private IPath  projectPath = null;
    private IJavaProject javaProject = null;
    private ISourceProject project = null;
    public FregeData(ISourceProject sourceProject) {
      project = sourceProject;
      if (project != null) {
        IProject rp = project.getRawProject();
       
        // System.out.println("The raw project has type: " + jp.getClass());
        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        IPath wroot = workspace.getRoot().getLocation();
        // IProjectNatureDescriptor[] nds = workspace.getNatureDescriptors();
        boolean isJava = false;
       
        try {
            isJava = rp.hasNature("org.eclipse.jdt.core.javanature");
           
        } catch (CoreException e) {
            // e.printStackTrace();
            // System.out.println("The " + nd.getNatureId() + " is not supported, or so it seems.");
        }

        if (isJava) {
          IJavaProject jp = JavaCore.create(rp);
          javaProject = jp;
          projectPath = jp.getPath();
          try {
            IResource bpres = workspace.getRoot().findMember(jp.getOutputLocation());
            bp = bpres != null
                  ? bpres.getLocation().toString()
                  : wroot.append(jp.getOutputLocation()).toPortableString();
            IClasspathEntry[] cpes = jp.getResolvedClasspath(true);
            fp = bp;
            sp = ".";
            for (IClasspathEntry cpe: cpes) {
              if (cpe.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
                if (sp.length() > 0) sp += System.getProperty("path.separator");
                sp += cpe.getPath().makeRelativeTo(jp.getPath()).toString();
              }
              else {
                if (fp.length() > 0) fp += System.getProperty("path.separator");
               
                IResource res = workspace.getRoot().findMember(cpe.getPath());
                String lib = res != null ? res.getLocation().toString() : "no res";
                String lib1 =  cpe.getPath().toString();
                String lib2 =  cpe.getPath().makeRelativeTo(jp.getPath()).toString();
                String lib3 =  cpe.getPath().makeRelativeTo(wroot).makeRelative().toString();
                String lib4 =  cpe.getPath().makeRelativeTo(wroot).toString();
                String lib5 =  cpe.getPath().makeRelativeTo(wroot).makeAbsolute().toString();
                if (new java.io.File(lib).exists()) fp += lib;
                else if (new java.io.File(lib1).exists()) fp += lib1;
                else if (new java.io.File(lib2).exists()) fp += lib2;
                else if (new java.io.File(lib3).exists()) fp += lib3;
                else if (new java.io.File(lib4).exists()) fp += lib4;
                else if (new java.io.File(lib5).exists()) fp += lib5;
                else {
                  System.err.println("WHOA!!! Neither of the following do exist: "
                      + lib + ", " + lib1 + ", " + lib2 + ", " + lib3
                      + ", " + lib4 + ", " + lib5);
                  System.err.println("JavaProject.getPath: " + jp.getPath());
                }
              }
            }
          } catch (JavaModelException e) {
          } catch (NullPointerException np) {
          }
        }
      }
      if (fp.equals("")) fp=".";
      if (sp.equals("")) sp=".";
    }
    public IPath getProjectPath() { return projectPath; }
    /**
     * The source path always includes the project directory, as otherwise source resolution in
     * linked directories will work only if one links below a source directory, which may not be
     * possible always.
     * @return the sp
     */
    public String getSp() {
      return sp;
    }
    /**
     * @return the fp
     */
    public String getFp() {
      return fp;
    }
    /**
     * @return the bp
     */
    public String getBp() {
      return bp;
    }
   
    /**
     * @return the java project
     */
    public IJavaProject getJp() { return javaProject; }
    /**
     * get all frege source files in the work space
     */
    public List<String> getAllSources(final String hint) {
      final FregeBuilder builder = new FregeBuilder();
      final Set<String> result = new HashSet<String>();
      try {
        project.getRawProject()
          .getWorkspace().getRoot()
          .accept(builder.fResourceVisitor);
      } catch (CoreException e) {
        // problems getting the file names
        return new ArrayList<String>(result);
      }
      LineNumberReader rdr = null;
      for (IFile file : builder.fChangedSources) try {
        rdr = null;
        rdr = new LineNumberReader(new InputStreamReader(file.getContents(true)));
        String line;
        java.util.regex.Pattern pat = Pattern.compile("\\b(package|module)\\s+((\\w|\\.)+)");
        while ((line = rdr.readLine()) != null) {
          Matcher m = pat.matcher(line);
          if (m.find()) {
            String p = m.group(2);
            if (p.startsWith(hint))
                result.add(p);
          }
        }
        rdr.close(); rdr = null;
      } catch (Exception e) {
        if (rdr != null)
          try {
            rdr.close();
          } catch (IOException e1) {
            rdr = null;
          }
        rdr = null;
      }
      ArrayList<String> sorted = new ArrayList<String>(result);
      Collections.sort(sorted);
      return sorted;
    }
    /**
     * look for a path that contains the source code for pack
     */
    public IPath getSource(final String pack) {
      final String fr = pack.replaceAll("\\.", "/") + ".fr";
      // final String[] srcs = getSp().split(System.getProperty("path.separator"));
      final FregeBuilder builder = new FregeBuilder();
      try {
        project.getRawProject()
          // .getWorkspace().getRoot()
          .accept(builder.fResourceVisitor);
      } catch (CoreException e) {
        // problems getting the file names
        return null;
      }
      for (IFile file : builder.fChangedSources) {
        IPath it = file.getFullPath();
        if (it.toString().endsWith(fr)) return it;
      }
      /*
      for (String sf: srcs) {
        final IPath p = new Path(sf + "/" + fr);
       
        final IResource toRes = project.getRawProject().findMember(p); 
       
        if (toRes != null && toRes instanceof IFile) {
          final IFile to = (IFile) toRes;
          return to.getFullPath();
        }
      }
      */
      return null;
    }
  }
 
  public FregeParseController() {
    super(FregePlugin.getInstance().getLanguageID());
  }

  private int timeout;
  private TGlobal global, goodglobal;
  private int  hash = 0;
  private int  leng = 0;
  private boolean tokensIteratorDone = false;
  private final ISourcePositionLocator   fSourcePositionLocator  
          = new FregeSourcePositionLocator(this);
    private final SimpleAnnotationTypeInfo fSimpleAnnotationTypeInfo
            = new SimpleAnnotationTypeInfo();
  public IMessageHandler msgHandler = null;
  private FregeData fregeData = null;
  private static Map<String, Lazy> packs = new HashMap<>();
 
  void initPacks() {
    boolean make = false;
    synchronized (packs) {
      make = packs.get(fregeData.getBp()) == null;
      if (make) {
        // Object value = PreludeBase.TST.performUnsafe(EclipseUtil.getpacks());
        packs.put(fregeData.getBp(), frege.lib.Modules.noPacks);
      }
    }
    if (make) {
      Job job = new Job("Getting Modules") {
        public IStatus run(IProgressMonitor moni) {
          moni.worked(10);
          Lazy value = Delayed.<Lazy>forced(
              PreludeBase.TST.performUnsafe(
                  Utilities.initRoot(
                      fregeData.getFp()
                      ) // .<Lambda>forced()
                      ));
          moni.worked(75);
          synchronized (packs) {
            packs.put(fregeData.getBp(),value);
          }
          System.err.println("Job done, value=" + value);
          moni.done();
          return Status.OK_STATUS;
        }
      };
      job.schedule();
    }
  }
 
  public Lazy ourRoot() {
    synchronized (packs) {
      return packs.get(fregeData.getBp());
    }
  }
 
  public static Lazy ourRoot(FregeParseController parser) {
    return parser.ourRoot();
  }
 
  public void justCompiled() {
    synchronized (packs) {
      Lazy x = ourRoot();
      Lazy y = Delayed.<Lazy>forced(
        PreludeBase.TST.performUnsafe(Utilities.justCompiled(global, x))
      );
      packs.put(fregeData.getBp(), y);
    }
  }
 
  /**
   * @author ingo
   * @return the frege data structure
   */
  public FregeData getFD() { return fregeData; }
  /**
   * tell if we have errors
   */
  public static int errors(TGlobal global) { return global == null ? 1 : TGlobal.errors(global); }
 
  /**
   * tell how far we are advanced
   */
  public static int achievement(TGlobal global) {
    if (global == null) return 0;
    final TSubSt sub = TGlobal.sub(global);
    return 2 * TSubSt.nextPass(sub) - (errors(global) > 0 ? 1 : 0);
  }
 
  /**
   * run a {@link frege.prelude.PreludeBase.TState} action and return the new TGlobal state
   * @return the new state
   */
  public static TGlobal runSTG(Lazy action, TGlobal g) {
    Lambda stg = Delayed.<Lambda>forced(action);        // State (g -> (a, g))
    TTuple2 r = TState.run(stg, g).<TTuple2>forced();
    return Delayed.<TGlobal>forced( r.mem2 );
  }
 
  /**
   * Run a {@link frege.prelude.PreludeBase.TState} action and return the result.
   * The state must not be changed by the action.
   * @return the result
   */
  public static Object funSTG(Lazy action, TGlobal g) {
    Lambda stg = action.<Lambda>forced();        // State (g -> (a, g))
    TTuple2 r = TState.run(stg, g).<TTuple2>forced();
    return r.mem1;
  }
 
  /**
   * run a {@link frege.prelude.PreludeBase.TStateT TGlobal IO} action and return the new TGlobal state
   * @return the new state
   */
  public static TGlobal runSTIO(Lazy action, TGlobal g) {
    Lambda stg = Delayed.<Lambda>forced(action);        // StateT (g -> IO (a, g))
    Lambda r   = Delayed.<Lambda>forced( TStateT.run(stg, g));
    TTuple2 t  = r.apply(42).result().<TTuple2>forced();
    return Delayed.<TGlobal>forced(t.mem2);
  }
 
  /**
   * Run a {@link frege.prelude.PreludeBase.TState} action and return the result.
   * The state must not be changed by the action.
   * @return the result
   */
  public static Object funSTIO(Lazy action, TGlobal g) {
    Lambda stg = Delayed.<Lambda>forced(action);        // StateT (g -> IO (a, g))
    Lambda r   = Delayed.<Lambda>forced( TStateT.run(stg, g));
    TTuple2 t  = r.apply(42).result().<TTuple2>forced();
    return t.mem1;
  }

  /**
   * @param filePath    Project-relative path of file
   * @param project    Project that contains the file
   * @param handler    A message handler to receive error messages (or any others)
   *             from the parser
   */
  public void initialize(IPath filePath, ISourceProject project,
      IMessageHandler handler) {
    super.initialize(filePath, project, handler);
    IPath fullFilePath = project != null ?
        project.getRawProject().getLocation().append(filePath)
        : filePath;

    global = Delayed.<TGlobal> forced(frege.prelude.PreludeBase.TST
        .performUnsafe(CompilerOptions.eclipseOptions
            .<Lambda> forced()));
    fregeData = new FregeData(project);
    initPacks();
    createLexerAndParser(fullFilePath, project);

    msgHandler = handler;
  }

  public IParser getParser() {
    new Exception("getParser: called").printStackTrace(System.out);
    return null; // parser;
  }

 
  public ISourcePositionLocator getNodeLocator() {
    return fSourcePositionLocator;
  }
 

 
  private void createLexerAndParser(IPath filePath, ISourceProject project) {
    System.err.println("createLexerAndParser: " + filePath.toPortableString());
    System.err.println("classpath: " + System.getProperty("java.class.path"));
   

    final FregeData data = fregeData;
    final String fp = data.getFp();  
    final String bp = data.getBp();
    final String sp = data.getSp();
    final IPath  pp = data.getProjectPath();
    final IPath  wk = ResourcesPlugin.getWorkspace().getRoot().getLocation();
    final String src = pp != null ? filePath
        .makeRelativeTo(wk)
        .makeAbsolute()
        .makeRelativeTo(pp).toString() : filePath.toString();

    // set source file into global
    global = TGlobal.upd$options(global, TOptions.upd$source(
        TGlobal.options(global),
        src));

    System.err.println("project Path: " + pp);
    System.err.println("source File: " + src);
       
    System.err.println("FregePath: " + fp);
    global = TGlobal.upd$options(global, TOptions.upd$path(
        TGlobal.options(global),
        frege.java.util.Regex.TRegex.splitted(
            Delayed.<Pattern>forced(frege.compiler.Utilities.pathRE),
            fp)));
    System.err.println("SourcePath: " + sp);
    global = TGlobal.upd$options(global, TOptions.upd$sourcePath(
        TGlobal.options(global),
        frege.java.util.Regex.TRegex.splitted(
            Delayed.<Pattern>forced(frege.compiler.Utilities.pathRE),
            sp)));
    System.err.println("Destination: " + bp);
    global = TGlobal.upd$options(global, TOptions.upd$dir(
        TGlobal.options(global),
        bp));
    global = runSTIO(Utilities.newLoader, global);
     
    IPreferencesService service = FregePlugin.getInstance().getPreferencesService();
    if (service != null) {
      timeout = service.getIntPreference(FregePreferencesConstants.P_PARSETIMEOUT);
      if (service.getBooleanPreference(FregePreferencesConstants.P_INLINE)) {
        global = TGlobal.upd$options(global, TOptions.upd$flags(
              TGlobal.options(global),
              Delayed.<Long> forced(
                TBitSet.unionE(new IEnum_Flag(),
                  TOptions.flags(TGlobal.options(global)),
                  TFlag.INLINE))
            ));
      } else {
        global = TGlobal.upd$options(global, TOptions.upd$flags(
            TGlobal.options(global),
            Delayed.<Long> forced(
              TBitSet.differenceE(new IEnum_Flag(),
                TOptions.flags(TGlobal.options(global)),
                TFlag.INLINE))
          ));
      }
      if (service.getBooleanPreference(FregePreferencesConstants.P_COMMENTS)) {
        global = TGlobal.upd$options(global, TOptions.upd$flags(
              TGlobal.options(global),
              Delayed.<Long> forced(
                TBitSet.unionE(new IEnum_Flag(),
                  TOptions.flags(TGlobal.options(global)),
                  TFlag.COMMENTS))
            ));
      } else {
        global = TGlobal.upd$options(global, TOptions.upd$flags(
            TGlobal.options(global),
            Delayed.<Long> forced(
              TBitSet.differenceE(new IEnum_Flag(),
                TOptions.flags(TGlobal.options(global)),
                TFlag.COMMENTS))
          ));
      }
      final String prefix = service.getStringPreference(FregePreferencesConstants.P_PREFIX);
      if (prefix != null && prefix.length() > 0) {
        global = TGlobal.upd$options(global, TOptions.upd$prefix(
              TGlobal.options(global), prefix));
      }
    }
    else timeout = 250;
    goodglobal = global;
  }

  public void resetHash() {
    leng = 0;
    hash = 0;
    tokensIteratorDone = false;
    global.mem$sub.mem$cache.put(TTree.DNil.it);
    global = runSTIO(Utilities.refreshPackages, global);
    System.err.println("packages cleared");
  }
 
  /**
   * The msgHandler must be in place
   */
  synchronized public TGlobal parse(String contents, boolean scanOnly,
      IProgressMonitor monitor) {
   
    long t0 = System.nanoTime();
    long te = 0;
    long t1 = 0;
    TList passes = null;
    DCons pass = null;
    int index;
   
    {
     
      if (monitor.isCanceled()) return global;
   
      if (contents.length() == leng && contents.hashCode() == hash) {
        return global;      // nothing really updated here
      }
   
   
      msgHandler.clearMessages();
   
      final IProgressMonitor myMonitor = monitor;
      Lambda cancel = new Fun1<Boolean>() {     
        public Boolean eval(Object realworld) {
          return myMonitor.isCanceled()
        }
      };
   
      global = TGlobal.upd$sub(global,  TSubSt.upd$cancelled(
        TGlobal.sub(global),
        cancel));
      global = TGlobal.upd$sub(global, TSubSt.upd$numErrors(TGlobal.sub(global), 0));
      global = TGlobal.upd$sub(global, TSubSt.upd$resErrors(TGlobal.sub(global), 0));
   
      passes = frege.compiler.Main.passes.<TList>forced();
     
      monitor.beginTask(this.getClass().getName() + " parsing",
          1 + IListView__lbrack_rbrack.length(passes));

      index = 0;

      while (!monitor.isCanceled()
          && (pass = passes._Cons()) != null
          && errors(global) == 0
          && index < 2) {    // do lexer and parser synchronized
        t1 = System.nanoTime();
        index++;
        passes = pass.mem2.<TList>forced();
        final TTuple2 adx = Delayed.<TTuple2>forced( pass.mem1 );
        final Lazy action = index == 1 ? Main.lexPassIDE(contents) : Delayed.delayed(adx.mem1);
        final String   desc   = Delayed.<String>forced(adx.mem2);
        final TGlobal g = runSTIO(action, global);
        te = System.nanoTime();
        System.err.println(desc + " took "
          + (te-t1)/1000000 + "ms, cumulative "
          + (te-t0)/1000000 + "ms");
       
        monitor.worked(1);
        global = runSTG(Utilities.passDone, g);
      }
      if (achievement(global) >= achievement(goodglobal))
        goodglobal = global;      // when opening a file with errors
      else {
        // update token array in goodglobal
        TToken[] toks = TSubSt.toks(TGlobal.sub(global));
        goodglobal = TGlobal.upd$sub(goodglobal, TSubSt.upd$toks(
            TGlobal.sub(goodglobal), toks));
      }
//      Array gtoks = TSubSt.toks(TGlobal.sub(global));
//      System.err.println("global.toks==good.toks is " + (toks == gtoks));
    }
   
    int needed = (int) ((te-t0) / 1000000);
       
    if (scanOnly && timeout - needed > 0 && errors(global) == 0 && !monitor.isCanceled())
      try { Thread.sleep(timeout - needed); } catch (InterruptedException e) {}
    t0 = System.nanoTime() - (te-t0);

   
    while (!monitor.isCanceled()
          && errors(global) == 0
          && (pass = passes._Cons()) != null) {      // do the rest unsynchronized
        t1 = System.nanoTime();
        passes = pass.mem2.<TList>forced();
        index++;
        final TTuple2 adx = Delayed.<TTuple2>forced( pass.mem1 );
        final Lazy action = Delayed.delayed(adx.mem1);
        final String   desc   = Delayed.<String>forced(adx.mem2);
        final TGlobal g = runSTIO(action, global);
        te = System.nanoTime();
        System.err.println(desc + " took "
          + (te-t1)/1000000 + "ms, cumulative "
          + (te-t0)/1000000 + "ms");
       
        monitor.worked(1);
        global = runSTG(Utilities.passDone, g);
       
        if (achievement(global) >= achievement(goodglobal))
          goodglobal = global;
        else if (index >= 6) {
          // give token resolve table to goodglobal
          goodglobal = TGlobal.upd$sub(goodglobal, TSubSt.upd$idKind(
              TGlobal.sub(goodglobal), TSubSt.idKind(TGlobal.sub(global))));
          // give locals to goodglobals
          goodglobal = TGlobal.upd$locals(goodglobal, TGlobal.locals(global));
        }
        if (scanOnly && desc.startsWith("type check")) {
          goodglobal = global;
          break;
        }
    }
   
    leng = contents.length();
    hash = contents.hashCode();
    return global;
  }

  @Override
  public TGlobal getCurrentAst() {
    // System.err.println("delivered goodglobal");
    return global;
  }
 
  synchronized public TGlobal getGoodAst() {
    // System.err.println("delivered goodglobal");
    return goodglobal;
  }
 
  @Override
  public TGlobal parse(String input, IProgressMonitor monitor) {
    MarkerCreatorWithBatching mcwb = msgHandler instanceof MarkerCreatorWithBatching ?
        (MarkerCreatorWithBatching) msgHandler : null;
    // when we build, we'll get a MarkerCreatorWithBatching
    // Hence, if we do not have one, we just scan&parse, otherwise we do a full compile
    TGlobal g = parse(input, mcwb == null, monitor);
    int u = TGlobal.unique(g);
    System.err.printf("frege parse: done, unique=%d, adding errors ", u);
    tokensIteratorDone = false;
    TList msgs = PreludeList.reverse(TSubSt.messages(TGlobal.sub(g)));
    int maxmsgs = 9;
    
    while (!monitor.isCanceled() && maxmsgs > 0) {
      TList.DCons node = msgs._Cons();
      if (node == null) break;
      msgs = node.mem2.<TList>forced();
      TMessage msg = Delayed.<TMessage>forced( node.mem1 );
      if (mcwb != null) {
        // do also warnings and hints
        int sev = IMarker.SEVERITY_ERROR;
        if (TMessage.level(msg) == TSeverity.HINT) sev = IMarker.SEVERITY_INFO;
        else if (TMessage.level(msg) == TSeverity.WARNING)
          sev = IMarker.SEVERITY_WARNING;
        try {
          mcwb.addMarker(sev,
              TMessage.text(msg)
                .replaceAll("\n", "   "),
              TToken.line( TPosition.first(TMessage.pos(msg)) ),
              TPosition.start(TMessage.pos(msg)),
              TPosition.end(TMessage.pos(msg)));
        } catch (LimitExceededException e) {
          break;
        }
        continue;
      }
      // normal message handling
      if (TMessage.level(msg) != TSeverity.ERROR) continue;
      maxmsgs--;
      System.err.print(".");
      msgHandler.handleSimpleMessage(TMessage.text(msg),
          TPosition.start(TMessage.pos(msg)),
          TPosition.end(TMessage.pos(msg))-1,
          0, 0, 0, 0);
    }
    if (mcwb == null) {
      monitor.done();
    }
    System.err.println(" returning to imp framework");
    return g;
  }
 
  @Override
  synchronized public Iterator<TToken> getTokenIterator(IRegion region) {
    System.err.print("getTokenIterator(): " +
        (global != null ? TGlobal.thisPack(global) : "???"));
    if (!tokensIteratorDone) {
      System.err.println("  some");
      tokensIteratorDone = true;
      return new TokensIterator(TSubSt.toks(TGlobal.sub(global)), region);
    }
    else {
      System.err.println("  none");
      return null; // new TokensIterator(new frege.runtime.Array(0), region);
    }
  }

  @Override
  public ISourcePositionLocator getSourcePositionLocator() {
    return fSourcePositionLocator;
  }

  @Override
  public IAnnotationTypeInfo getAnnotationTypeInfo() {
    return fSimpleAnnotationTypeInfo;
  }
 
  private ILanguageSyntaxProperties lsp;
  /**
     * @return an implementation of {@link ILanguageSyntaxProperties} that
     * describes certain syntactic features of this language
     */
  @Override
  public ILanguageSyntaxProperties getSyntaxProperties() {
    if (lsp == null) {
      lsp = new ILanguageSyntaxProperties() {
       
        @Override
        public String getSingleLineCommentPrefix() {
          return "--";
        }
       
        @Override
        public String getIdentifierConstituentChars() {
          return null;
        }
       
        @Override
        public int[] getIdentifierComponents(String ident) {
          return null;
        }
       
        @Override
        public String[][] getFences() {
          return new String[][] { {"(", ")"}, {"{", "}"}, {"[", "]"}};
        }
       
        @Override
        public String getBlockCommentStart() {
          return "{-";
        }
       
        @Override
        public String getBlockCommentEnd() {
          return "-}";
        }
       
        @Override
        public String getBlockCommentContinuation() {
          return null;
        }
      };
    }
    return lsp;
  }
  public synchronized final int getHash() {
    return hash;
  }
  public synchronized final int getLeng() {
    return leng;
  }
 
  /**
   * look for a path that contains the source code for pack in the context of this parser
   */
  public IPath getSource(final String pack) {
    // find it in the sources of this project
    final IPath psrc = getFD().getSource(pack);
    if (psrc != null) return psrc;
    // get it via classloader
    final String fr = pack.replaceAll("\\.", "/") + ".fr";    // the file name
    final String segments[] = pack.split("\\.");
    if (this.fProject == null) return null;                     // too bad, doesn't work with project.
    // final IProject rp = this.fProject.getRawProject();
    final IJavaProject jp = getFD().getJp();
    IWorkspace workspace = ResourcesPlugin.getWorkspace();
    IPath wroot = workspace.getRoot().getLocation();
   
    IFile newsrc = null;
    IPath srcpath = null;
    IPath binPath = null;
    try {
      binPath = jp.getOutputLocation();
    } catch (JavaModelException e) {
      return null;
    }

    srcpath = binPath.append(fr);
    newsrc = workspace.getRoot().getFile(srcpath);
    if (newsrc == null) return null// couldn't get file handle here
    if (newsrc.exists()) return srcpath;
   
    IFolder folder = workspace.getRoot().getFolder(binPath);
    // System.err.println("Parser.getSource start in folder " + folder.getLocation());
    InputStream stream = null;
   
    try {
      // create the intermediate directories
      for (int i=0; i < segments.length-1; i++) {
        binPath = binPath.append(segments[i]);
        folder = workspace.getRoot().getFolder(binPath);
        // System.err.println("Parser.getSource continue in folder " + folder.getLocation());
        if (folder.exists()) {
          // System.err.println("Parser.getSource exists " + folder.getLocation());
        }
        else {
          // System.err.println("Parser.getSource creating " + folder.getLocation());
          folder.create(true, true, null);
        }
      }

      final TSubSt subst = TGlobal.sub(this.global);
      final URLClassLoader loader = TSubSt.loader(subst);
      stream = loader.getResourceAsStream(fr);
      if (stream == null) return null;        // not here :-(
      newsrc.create(stream, IResource.FORCE | IResource.DERIVED, new NullProgressMonitor());
    } catch (CoreException e) {
      System.err.println(e.getMessage());
      return null;
    } finally {
      try { if (stream != null) stream.close(); } catch (IOException ioe) {}
    }
    return srcpath;
  }
 
}
TOP

Related Classes of frege.imp.parser.FregeParseController$FregeData

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.