Package org.rascalmpl.interpreter.matching

Source Code of org.rascalmpl.interpreter.matching.ConcreteApplicationPattern$LexicalTreeAsTuple

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

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.eclipse.imp.pdb.facts.IAnnotatable;
import org.eclipse.imp.pdb.facts.IConstructor;
import org.eclipse.imp.pdb.facts.IList;
import org.eclipse.imp.pdb.facts.ITuple;
import org.eclipse.imp.pdb.facts.IValue;
import org.eclipse.imp.pdb.facts.IWithKeywordParameters;
import org.eclipse.imp.pdb.facts.exceptions.FactTypeUseException;
import org.eclipse.imp.pdb.facts.exceptions.IllegalOperationException;
import org.eclipse.imp.pdb.facts.type.Type;
import org.eclipse.imp.pdb.facts.visitors.IValueVisitor;
import org.rascalmpl.interpreter.IEvaluatorContext;
import org.rascalmpl.interpreter.env.Environment;
import org.rascalmpl.interpreter.result.Result;
import org.rascalmpl.interpreter.result.ResultFactory;
import org.rascalmpl.semantics.dynamic.Tree;
import org.rascalmpl.values.uptr.ProductionAdapter;
import org.rascalmpl.values.uptr.SymbolAdapter;
import org.rascalmpl.values.uptr.TreeAdapter;

public class ConcreteApplicationPattern extends AbstractMatchingResult {
  private IList subjectArgs;
  private final IMatchingResult tupleMatcher;
  private IConstructor production;
  private final ITuple tupleSubject;
  private final Type myType;
  private boolean isLiteral;

  public ConcreteApplicationPattern(IEvaluatorContext ctx, Tree.Appl x, List<IMatchingResult> list) {
    super(ctx, x);
   
    // retrieve the static value of the production of this pattern
    this.production = x.getProduction();
   
    // use a tuple pattern to match the children of this pattern
    this.tupleMatcher = new TuplePattern(ctx, x, list);
   
    // this prototype can be used for every subject that comes through initMatch
    this.tupleSubject = ProductionAdapter.isLexical(production) ? new LexicalTreeAsTuple() : new TreeAsTuple();
   
    // save the type of this tree
    this.myType = x._getType();
  }
 
  public List<IVarPattern> getVariables() {
    return tupleMatcher.getVariables();
  }
 
  private class TreeAsTuple implements ITuple {
    // notice how this class skips the layout nodes...
   
    public int arity() {
      return (subjectArgs.length() + 1) / 2;
    }

    public IValue get(int i) throws IndexOutOfBoundsException {
      IConstructor arg = (IConstructor) subjectArgs.get(i * 2);
//      if (TreeAdapter.isList(arg)) {
//        return TreeAdapter.getArgs(arg);
//      }
      return arg;
    }

    public Type getType() {
      Type[] fields = new Type[arity()];
      for (int i = 0; i < fields.length; i++) {
        fields[i] = get(i).getType();
      }
      return tf.tupleType(fields);
    }

    public boolean isEqual(IValue other) {
      if (!(other instanceof ITuple)) {
        return false;
      }
     
      if (arity() != ((ITuple) other).arity()) {
        return false;
      }
     
      int i = 0;
      for (IValue otherChild : (ITuple) other) {
        if (!get(i++).isEqual(otherChild)) {
          return false;
        }
      }
     
      return true;
    }

   
    public Iterator<IValue> iterator() {
      return new Iterator<IValue>() {
        int currentIndex = 0;

        public boolean hasNext() {
          return currentIndex < arity();
        }

        public IValue next() {
          return get(currentIndex++);
        }

        public void remove() {
          throw new UnsupportedOperationException();
        }
      };
    }

    public IValue get(String label) throws FactTypeUseException {
      throw new UnsupportedOperationException();
    }

    public IValue select(int... fields) throws IndexOutOfBoundsException {
      throw new UnsupportedOperationException();
    }

    @Override
    public IValue selectByFieldNames(String... fields) throws FactTypeUseException {
      throw new UnsupportedOperationException();
    }

    public ITuple set(int i, IValue arg) throws IndexOutOfBoundsException {
      throw new UnsupportedOperationException();
    }

    public ITuple set(String label, IValue arg) throws FactTypeUseException {
      throw new UnsupportedOperationException();
    }

    public <T, E extends Throwable> T accept(IValueVisitor<T,E> v) throws E {
      throw new UnsupportedOperationException();
    }
   
    @Override
    public boolean isAnnotatable() {
      return false;
    }

    @Override
    public IAnnotatable<? extends IValue> asAnnotatable() {
      throw new IllegalOperationException(
          "Cannot be viewed as annotatable.", getType());
    }
   
    @Override
    public boolean mayHaveKeywordParameters() {
      return false;
    }
   
    @Override
    public IWithKeywordParameters<? extends IValue> asWithKeywordParameters() {
      throw new IllegalOperationException(
          "Cannot be viewed as with keyword parameters", getType());
    }

  }
 
  private class LexicalTreeAsTuple extends TreeAsTuple {
    // notice how this class does not skip the layout nodes...
    public int arity() {
      return subjectArgs.length();
    }

    public IValue get(int i) throws IndexOutOfBoundsException {
      return subjectArgs.get(i);
    }
  }
 

  @Override
  public void initMatch(Result<IValue> subject) {
    hasNext = false;
    Type subjectType = subject.getValue().getType();
    super.initMatch(subject);

    if(subjectType.isAbstractData()){
      IConstructor treeSubject = (IConstructor)subject.getValue();
   
      if (!TreeAdapter.isAppl(treeSubject)) {
        // fail early if the subject is an ambiguity cluster
        hasNext = false;
        return;
      }

      if (!SymbolAdapter.isLiteral(ProductionAdapter.getType(production))) {
        if (!TreeAdapter.getProduction(treeSubject).isEqual(production)) {
          // fail early if the subject's production is not the same
          hasNext = false;
          return;
        }
       
        this.subjectArgs = TreeAdapter.getArgs(treeSubject);
        tupleMatcher.initMatch(ResultFactory.makeResult(tupleSubject.getType(), tupleSubject, ctx));
     
        hasNext = tupleMatcher.hasNext();
        isLiteral = false;
      }
      else {
        isLiteral = true;
        hasNext = true;
      }
    }
  }
 
  @Override
  public boolean hasNext() {
    if (!isLiteral) {
      return tupleMatcher.hasNext();
    }
   
    return true;
  }
 
  @Override
  public boolean next(){
    checkInitialized();
   
    if (hasNext && !isLiteral) {
      return tupleMatcher.next();
    }
    else if (hasNext){
      hasNext = false;
      return true;
    }
   
    return false;
  }

  @Override
  public Type getType(Environment env,
      HashMap<String, IVarPattern> patternVars) {
    return myType;
  }
 
  @Override
  public String toString() {
    return production.toString();
  }
 
}
TOP

Related Classes of org.rascalmpl.interpreter.matching.ConcreteApplicationPattern$LexicalTreeAsTuple

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.