Package org.rascalmpl.interpreter.matching

Source Code of org.rascalmpl.interpreter.matching.IteratorFactory

/*******************************************************************************
* 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
*   * Emilie Balland - (CWI)
*   * Paul Klint - Paul.Klint@cwi.nl - CWI
*   * Mark Hills - Mark.Hills@cwi.nl (CWI)
*   * Arnold Lankamp - Arnold.Lankamp@cwi.nl
*******************************************************************************/
package org.rascalmpl.interpreter.matching;

import java.util.Iterator;

import org.eclipse.imp.pdb.facts.IConstructor;
import org.eclipse.imp.pdb.facts.IList;
import org.eclipse.imp.pdb.facts.IMap;
import org.eclipse.imp.pdb.facts.INode;
import org.eclipse.imp.pdb.facts.ISet;
import org.eclipse.imp.pdb.facts.ITuple;
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.interpreter.IEvaluatorContext;
import org.rascalmpl.interpreter.result.Result;
import org.rascalmpl.interpreter.staticErrors.NotEnumerable;
import org.rascalmpl.interpreter.staticErrors.UnexpectedType;
import org.rascalmpl.interpreter.staticErrors.UnsupportedOperation;
import org.rascalmpl.interpreter.types.NonTerminalType;
import org.rascalmpl.interpreter.types.RascalTypeFactory;
import org.rascalmpl.interpreter.types.TypeReachability;
import org.rascalmpl.values.uptr.SymbolAdapter;
import org.rascalmpl.values.uptr.TreeAdapter;

public class IteratorFactory {
 
  public static Type elementType(IEvaluatorContext ctx, Result<IValue> subject) {
    Type subjectType = subject.getType();

    if (subjectType.isList() || subjectType.isSet()) {
      return subjectType.getElementType();
    }
    else if (subjectType.isMap()){       
      return subjectType.getKeyType();
    }
    else if (subjectType.isExternalType()){
      if (subjectType instanceof NonTerminalType){
        NonTerminalType nt = (NonTerminalType) subjectType;

        if (nt.isConcreteListType() || nt.isOptionalType()){
          IConstructor listSymbol = nt.getSymbol();
          return RascalTypeFactory.getInstance().nonTerminalType(SymbolAdapter.getSymbol(listSymbol));
        }
      }

      throw new NotEnumerable(subjectType.toString(), ctx.getCurrentAST());
    }
    else if (subjectType.isNode() || subjectType.isAbstractData() || subjectType.isTuple()) {
      return TypeFactory.getInstance().valueType();     
    }
   
    throw new NotEnumerable(subjectType.toString(), ctx.getCurrentAST());
  }

  public static Iterator<IValue> make(IEvaluatorContext ctx, IMatchingResult matchPattern,
      Result<IValue> subject, boolean shallow){

    Type subjectType = subject.getType();
    IValue subjectValue = subject.getValue();
    Type patType = matchPattern.getType(ctx.getCurrentEnvt(), null);

    if (subjectType.isTop()) {
      System.err.println("???");
    }
    // TODO: this should be a visitor design as well..

    // List
    if(subjectType.isList()){
      //TODO: we could do this more precisely       
      if(shallow){
        checkMayOccur(patType, subjectType.getElementType(), ctx);
        return ((IList) subjectValue).iterator();
      }
      return new DescendantReader(subjectValue, false);

      // Set
    } else   if(subjectType.isSet()){       
      if (shallow){
        checkMayOccur(patType, subjectType.getElementType(), ctx);
        return ((ISet) subjectValue).iterator();
      }
     
      return new DescendantReader(subjectValue, false);

      // Map
    } else if(subjectType.isMap()){       
      if (shallow) {
        checkMayOccur(patType, subjectType.getKeyType(), ctx);
        return ((IMap) subjectValue).iterator();
      }
      return new DescendantReader(subjectValue, false);
    } else if (subjectType.isExternalType()) {
      if (subjectType instanceof NonTerminalType) {
        // NonTerminal (both pattern and subject are non-terminals, so we can skip layout and stuff)
        IConstructor tree = (IConstructor) subjectValue;
        NonTerminalType nt = (NonTerminalType) subjectType;

        if (!shallow) {
          return new DescendantReader(tree, patType instanceof NonTerminalType);
        }
        else {
          if (nt.isConcreteListType()){
            checkMayOccur(patType, subjectType, ctx);
            IConstructor ls = nt.getSymbol();

            int delta = SymbolAdapter.isSepList(ls) ?
                (SymbolAdapter.getSeparators(ls).length() + 1) : 1;

            return new CFListIterator(TreeAdapter.getArgs(tree), delta);
          }
          else if (nt.isOptionalType()) {
            checkMayOccur(patType, subjectType, ctx);
            return new CFListIterator(TreeAdapter.getArgs(tree), 1);
          }
        }
      }

      throw new NotEnumerable(subjectType.toString(), ctx.getCurrentAST());
      // Node and ADT
    } else if(subjectType.isNode() || subjectType.isAbstractData()){     
      if (shallow){
        if(subjectType.isAbstractData())
          checkMayOccur(patType, subjectType, ctx);
        return new NodeChildIterator((INode) subjectValue);
      }
      return new DescendantReader(subjectValue, false);

    } else if(subjectType.isTuple()){
      if(shallow){
        Type lub = TypeFactory.getInstance().voidType();
        int nElems = subjectType.getArity();
        for(int i = 0; i < nElems; i++)
          lub = lub.lub(subjectType.getFieldType(i));
        if(!lub.comparable(patType))
          throw new UnexpectedType(patType, subjectType, ctx.getCurrentAST())
        return new TupleElementIterator((ITuple)subjectValue);
      }
      return new DescendantReader(subjectValue, false);

    } else if(subjectType.isBool() ||
        subjectType.isInteger() ||
        subjectType.isReal() ||
        subjectType.isString() ||
        subjectType.isSourceLocation() ||
        subjectType.isRational() ||
        subjectType.isDateTime())
    {
      if (shallow) {
        throw new NotEnumerable(subjectType.toString(), ctx.getCurrentAST());
      }
      return new SingleIValueIterator(subjectValue);
    } else {
      throw new UnsupportedOperation("makeIterator", subjectType, ctx.getCurrentAST());
    }
  }

  private static void checkMayOccur(Type patType, Type rType, IEvaluatorContext ctx){
    if(!TypeReachability.mayOccurIn(patType, rType, ctx.getCurrentEnvt())) {
      throw new UnexpectedType(rType, patType, ctx.getCurrentAST());
    }
  }

}
TOP

Related Classes of org.rascalmpl.interpreter.matching.IteratorFactory

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.