Package org.rascalmpl.interpreter.matching

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

/*******************************************************************************
* 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 static org.rascalmpl.interpreter.result.ResultFactory.makeResult;

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

import org.eclipse.imp.pdb.facts.IConstructor;
import org.eclipse.imp.pdb.facts.IList;
import org.eclipse.imp.pdb.facts.IValue;
import org.eclipse.imp.pdb.facts.type.Type;
import org.rascalmpl.ast.AbstractAST;
import org.rascalmpl.interpreter.IEvaluatorContext;
import org.rascalmpl.interpreter.env.Environment;
import org.rascalmpl.interpreter.result.ResultFactory;
import org.rascalmpl.interpreter.staticErrors.RedeclaredVariable;
import org.rascalmpl.interpreter.types.NonTerminalType;
import org.rascalmpl.interpreter.utils.Names;
import org.rascalmpl.values.uptr.Factory;
import org.rascalmpl.values.uptr.SymbolAdapter;
import org.rascalmpl.values.uptr.TreeAdapter;

public class ConcreteListVariablePattern extends AbstractMatchingResult implements IVarPattern {
  private String name;
  private NonTerminalType declaredType;
 
  private boolean anonymous = false;
  private boolean debug = false;
  private boolean iDeclaredItMyself;
 
  public ConcreteListVariablePattern(IEvaluatorContext ctx, AbstractAST x,
      org.eclipse.imp.pdb.facts.type.Type type, org.rascalmpl.ast.Name name) {
    super(ctx, x);
    this.name = Names.name(name);
    this.declaredType = (NonTerminalType) type;
    this.anonymous = Names.name(name).equals("_");
    this.iDeclaredItMyself = false;
    //System.err.println("ConcreteListVariablePattern");
  }

  public ConcreteListVariablePattern(IEvaluatorContext ctx, AbstractAST x,
      org.eclipse.imp.pdb.facts.type.Type type, String name) {
    super(ctx, x);
    this.name = name;
    this.declaredType = (NonTerminalType) type;
    this.anonymous = name.equals("_");
    this.iDeclaredItMyself = false;
    //System.err.println("ConcreteListVariablePattern");
  }
 
  @Override
  public Type getType(Environment env, HashMap<String,IVarPattern> patternVars) {
    return declaredType;
  }

  @Override
  public List<IVarPattern> getVariables() {
    java.util.LinkedList<IVarPattern> res = new java.util.LinkedList<IVarPattern>();
    res.addFirst(this);
    return res;
  }

  public String getName() {
    return name;
  }

  public boolean isAnonymous() {
    return anonymous;
  }

  @Override
  public boolean next() {
    if (debug) {
      System.err.println("AbstractConcreteSyntaxListVariable.next");
    }
    checkInitialized();
    if (!hasNext)
      return false;
    hasNext = false;
   
   
    if (debug) {
      System.err.println("Subject: " + subject + " name: " + name
          + " getType: ");
     
      System.err.println("AbstractConcreteSyntaxListVariable.next: " + subject
          + "(type=" + subject.getType() + ") with " + declaredType
          + " " + name);
    }
 
    if (!anonymous && !iDeclaredItMyself && !ctx.getCurrentEnvt().declareVariable(declaredType, name)) {
      throw new RedeclaredVariable(name, ctx.getCurrentAST());
    }
   
    iDeclaredItMyself = true;
   
    if (subject.getType().isSubtypeOf(Factory.Args)) {
      if (((IList)subject.getValue()).isEmpty()) {
        IConstructor sym =declaredType.getSymbol();
        if (SymbolAdapter.isIterPlus(sym) || SymbolAdapter.isIterPlusSeps(sym)) {
          return false;
        }
      }
      if (!anonymous)
        ctx.getCurrentEnvt().storeVariable(name, makeResult(declaredType,
            wrapWithListProd(subject.getValue()), ctx));
      if (debug) {
        System.err.println("matches");
      }
      return true;
    }
   
    IConstructor subjectTree = (IConstructor) subject.getValue();
    if (TreeAdapter.isList(subjectTree)) {
      if ((TreeAdapter.getArgs(subjectTree)).isEmpty()) {
        IConstructor sym = declaredType.getSymbol();
        if (SymbolAdapter.isIterPlus(sym|| (SymbolAdapter.isIterPlusSeps(sym))) {
          return false;
        }
      }
     
      // This code makes sure that the call is allowed. It verifies first that either the declared type
      // is *, with the subject then either + or *; or that the declared type is +, with the subject
      // then forced to be +. Second, it checks that both either use, or do not use, separators, so
      // lists where one does and one does not use separators will not match. Finally, it makes sure
      // both use the same iterated symbol.
      IConstructor subjectListType = TreeAdapter.getType(subjectTree);
      IConstructor declaredListType = declaredType.getSymbol();
      if ( (SymbolAdapter.isStarList(declaredListType) && SymbolAdapter.isAnyList(subjectListType)) || (SymbolAdapter.isPlusList(declaredListType) && SymbolAdapter.isPlusList(subjectListType))) {
        if (SymbolAdapter.isSepList(declaredListType) == SymbolAdapter.isSepList(subjectListType)) {
          if (SymbolAdapter.getSymbol(subjectListType).equals(SymbolAdapter.getSymbol(declaredListType))) {
            ctx.getCurrentEnvt().storeVariable(name, ResultFactory.makeResult(declaredType, subject.getValue(), ctx));
           
            return true;
          }
        }
      }
     
      return false;
    }
   
    return false;
  }


  private IValue wrapWithListProd(IValue subject) {
    IList args = (IList) subject;
    IValue prod = ctx.getValueFactory().constructor(Factory.Production_Regular, declaredType.getSymbol());
   
    if (args.length() == 1) {
      IConstructor arg = (IConstructor) args.get(0);
     
      if (TreeAdapter.isList(arg) && TreeAdapter.getProduction(arg).isEqual(prod)) {
        return arg;
      }
    }
   
    return ctx.getValueFactory().constructor(Factory.Tree_Appl, prod, subject);
  }

  @Override
  public String toString() {
    return declaredType + " " + name + ":=" + subject;
  }

  @Override
  public boolean isVarIntroducing() {
    return iDeclaredItMyself;
  }
 
  public boolean isPlusList() {
    IConstructor sym =declaredType.getSymbol();
    return SymbolAdapter.isIterPlus(sym) || SymbolAdapter.isIterPlusSeps(sym);
  }

  @Override
  public String name() {
    return getName();
  }

  @Override
  public Type getType() {
    return declaredType;
  }
}
TOP

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

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.