Package org.rascalmpl.interpreter.env

Source Code of org.rascalmpl.interpreter.env.GlobalEnvironment$ParserTuple

/*******************************************************************************
* Copyright (c) 2009-2013 CWI
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:

*   * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
*   * Tijs van der Storm - Tijs.van.der.Storm@cwi.nl
*   * Paul Klint - Paul.Klint@cwi.nl - CWI
*   * Arnold Lankamp - Arnold.Lankamp@cwi.nl
*******************************************************************************/
package org.rascalmpl.interpreter.env;

import java.net.URI;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.imp.pdb.facts.IConstructor;
import org.eclipse.imp.pdb.facts.IMap;
import org.eclipse.imp.pdb.facts.ISourceLocation;
import org.eclipse.imp.pdb.facts.IValue;
import org.eclipse.imp.pdb.facts.type.Type;
import org.eclipse.imp.pdb.facts.type.TypeFactory;
import org.rascalmpl.ast.AbstractAST;
import org.rascalmpl.ast.QualifiedName;
import org.rascalmpl.interpreter.asserts.ImplementationError;
import org.rascalmpl.interpreter.result.AbstractFunction;
import org.rascalmpl.interpreter.result.ICallableValue;
import org.rascalmpl.interpreter.staticErrors.UndeclaredModule;
import org.rascalmpl.interpreter.utils.Names;
import org.rascalmpl.parser.gtd.IGTD;


/**
* The global environment represents the heap of Rascal.
* The stack is initialized with a bottom frame, which represent the shell
* environment.
*
*/
public class GlobalEnvironment {
  /** The heap of Rascal */
  private final HashMap<String, ModuleEnvironment> moduleEnvironment = new HashMap<String, ModuleEnvironment>();
   
  /** Keeping track of module locations */
  private final HashMap<String, URI> moduleLocations = new HashMap<String,URI>();
  private final HashMap<URI, String> locationModules = new HashMap<URI,String>();
 
  /**
   * Source location resolvers map user defined schemes to primitive schemes
   */
  private final HashMap<String, ICallableValue> sourceResolvers = new HashMap<String, ICallableValue>();
 
  /** Keeping track of generated parsers */
  private final HashMap<String,ParserTuple> objectParsersForModules = new HashMap<String,ParserTuple>();
  private final HashMap<String,ParserTuple> rascalParsersForModules = new HashMap<String,ParserTuple>();

  private boolean bootstrapper;
 
  public void clear() {
    moduleEnvironment.clear();
    moduleLocations.clear();
    locationModules.clear();
    sourceResolvers.clear();
    objectParsersForModules.clear();
    rascalParsersForModules.clear();
  }
 
  /**
   * Register a source resolver for a specific scheme. Will overwrite the previously
   * registered source resolver for this scheme.
   *
   * @param scheme   intended be a scheme name without + or :
   * @param function a Rascal function of type `loc (loc)`
   */
  public void registerSourceResolver(String scheme, ICallableValue function) {
    sourceResolvers.put(scheme, function);
  }
 
  public ISourceLocation resolveSourceLocation(ISourceLocation loc) {
    String scheme = loc.getURI().getScheme();
    int pos;
   
    ICallableValue resolver = sourceResolvers.get(scheme);
    if (resolver == null) {
      for (char sep : new char[] {'+',':'}) {
        pos = scheme.indexOf(sep);
        if (pos != -1) {
          scheme = scheme.substring(0, pos);
        }
      }

      resolver = sourceResolvers.get(scheme);
      if (resolver == null) {
        return loc;
      }
    }
   
    Type[] argTypes = new Type[] { TypeFactory.getInstance().sourceLocationType() };
    IValue[] argValues = new IValue[] { loc };
   
    return (ISourceLocation) resolver.call(argTypes, argValues, null).getValue();
  }
 
  /**
   * Allocate a new module on the heap
   * @param name
   */
  public ModuleEnvironment addModule(ModuleEnvironment mod) {
    assert mod != null;
    ModuleEnvironment env = moduleEnvironment.get(mod.getName());
    if (env == null) {
      moduleEnvironment.put(mod.getName(), mod);
      return mod;
    }
    else if (env == mod) {
      return mod;
    }
    else {
      throw new ImplementationError("Reinstantiating same module " + mod.getName());
    }
  }
 
  public ModuleEnvironment resetModule(String name) {
    ModuleEnvironment mod = moduleEnvironment.get(name);
    mod.reset();
    return mod;
  }
   
  /**
   * Retrieve a module from the heap
   */
  public ModuleEnvironment getModule(String name) {
    return moduleEnvironment.get(name);
  }

  public ModuleEnvironment getModule(QualifiedName name, AbstractAST ast) {
    ModuleEnvironment module = getModule(Names.fullName(name));
    if (module == null) {
      throw new UndeclaredModule(Names.fullName(name), ast);
    }
    return module;
  }
 

  public boolean existsModule(String name) {
    return moduleEnvironment.containsKey(name);
  }

 
  @Override
  public String toString(){
    StringBuffer res = new StringBuffer();
    res.append("heap.modules: ");
    for (String mod : moduleEnvironment.keySet()) {
      res.append(mod + ",");
    }
    return res.toString();
  }

  public void removeModule(ModuleEnvironment env) {
    moduleEnvironment.remove(env.getName());
  }

  public void setModuleURI(String name, URI location) {
    moduleLocations.put(name, location);
    locationModules.put(location, name);
  }
 
  public URI getModuleURI(String name) {
    return moduleLocations.get(name);
  }
 
  public String getModuleForURI(URI location) {
    return locationModules.get(location);
  }

  /**
   * A utility method for getting the right environment for a qualified name in a certain context.
   *
   * @param current  the current environment
   * @return current if the given name is not qualifed, otherwise it returns the environment that the qualified name points to
   */
  public Environment getEnvironmentForName(QualifiedName name, Environment current) {
    if (Names.isQualified(name)) {
      ModuleEnvironment mod = getModule(Names.moduleName(name));
      if (mod == null) {
        throw new UndeclaredModule(Names.moduleName(name), name);
      }
      return mod;
    }

    return current;
  }
 
  public Class<IGTD<IConstructor, IConstructor, ISourceLocation>> getObjectParser(String module, IMap productions) {
    return getParser(objectParsersForModules, module, productions);
  }
 
  public Class<IGTD<IConstructor, IConstructor, ISourceLocation>> getRascalParser(String module, IMap productions) {
    return getParser(rascalParsersForModules, module, productions);
  }
 
  /**
   * Retrieves a parser for a module.
   *
   * @param module
   * @param productions
   */
  private Class<IGTD<IConstructor, IConstructor, ISourceLocation>> getParser(Map<String,ParserTuple> store, String module, IMap productions) {
    ParserTuple parser = store.get(module);
    if(parser != null && parser.getProductions().isEqual(productions)) {
      return parser.getParser();
    }
   
    return null;
  }
 
  public void storeObjectParser(String module, IMap productions, Class<IGTD<IConstructor, IConstructor, ISourceLocation>> parser) {
    storeParser(objectParsersForModules, module, productions, parser);
  }
 
  public void storeRascalParser(String module, IMap productions, Class<IGTD<IConstructor, IConstructor, ISourceLocation>> parser) {
    storeParser(rascalParsersForModules, module, productions, parser);
  }
 
  private static void storeParser(HashMap<String, ParserTuple> store, String module, IMap productions, Class<IGTD<IConstructor, IConstructor, ISourceLocation>> parser) {
    ParserTuple newT = new ParserTuple(productions, parser);
    store.put(module, newT);
  }
 
  public Set<String> getImportingModules(String mod) {
    Set<String> result = new HashSet<String>();
   
    for (ModuleEnvironment env : moduleEnvironment.values()) {
      if (env.getImports().contains(mod)) {
        result.add(env.getName());
      }
    }
   
    return result;
  }
 
  public Set<String> getExtendingModules(String mod) {
    Set<String> result = new HashSet<String>();
    List<String> todo = new LinkedList<String>();
    todo.add(mod);
   
    while (!todo.isEmpty()) {
      String next = todo.remove(0);
     
      for (ModuleEnvironment env : moduleEnvironment.values()) {
        if (env.getExtends().contains(next)) {
          if (!result.contains(next)) {
            todo.add(env.getName());
            result.add(next);
            todo.removeAll(result);
          }
        }
      }
      result.add(next);
    }
   
    result.remove(mod);
    return result;
  }
 
  private static class ParserTuple {
    private final IMap production;
    private final Class<IGTD<IConstructor, IConstructor, ISourceLocation>> parser;

    public ParserTuple(IMap productions, Class<IGTD<IConstructor, IConstructor, ISourceLocation>> parser) {
      this.production = productions;
      this.parser = parser;
    }
   
    public IMap getProductions() {
      return production;
    }
   
    public Class<IGTD<IConstructor, IConstructor, ISourceLocation>> getParser() {
      return parser;
    }
  }
 
  public AbstractFunction getResourceImporter(String resourceScheme) {
    for (ModuleEnvironment menv : this.moduleEnvironment.values()) {
      if (menv.hasImporterForResource(resourceScheme))
        return menv.getResourceImporter(resourceScheme);
    }
    return null;
  }

  public void isBootstrapper(boolean b) {
    this.bootstrapper = b;
  }
 
  public boolean isBootstrapper() {
    return bootstrapper;
  }
}
TOP

Related Classes of org.rascalmpl.interpreter.env.GlobalEnvironment$ParserTuple

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.