Package org.rascalmpl.interpreter.result

Source Code of org.rascalmpl.interpreter.result.TupleResult

/*******************************************************************************
* 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
*   * Anastasia Izmaylova - A.Izmaylova@cwi.nl - CWI
*******************************************************************************/
package org.rascalmpl.interpreter.result;

import static org.rascalmpl.interpreter.result.ResultFactory.makeResult;

import org.eclipse.imp.pdb.facts.IBool;
import org.eclipse.imp.pdb.facts.IInteger;
import org.eclipse.imp.pdb.facts.ITuple;
import org.eclipse.imp.pdb.facts.IValue;
import org.eclipse.imp.pdb.facts.exceptions.UndeclaredFieldException;
import org.eclipse.imp.pdb.facts.type.Type;
import org.eclipse.imp.pdb.facts.type.TypeStore;
import org.rascalmpl.ast.Field;
import org.rascalmpl.ast.Name;
import org.rascalmpl.interpreter.IEvaluatorContext;
import org.rascalmpl.interpreter.staticErrors.UndeclaredField;
import org.rascalmpl.interpreter.staticErrors.UnexpectedType;
import org.rascalmpl.interpreter.staticErrors.UnsupportedSubscript;
import org.rascalmpl.interpreter.staticErrors.UnsupportedSubscriptArity;
import org.rascalmpl.interpreter.utils.Names;
import org.rascalmpl.interpreter.utils.RuntimeExceptionFactory;
import org.rascalmpl.values.ValueFactoryFactory;

public class TupleResult extends ElementResult<ITuple> {
 
  public TupleResult(Type type, ITuple tuple, IEvaluatorContext ctx) {
    super(type, tuple, ctx);
  }

  @Override
  public <U extends IValue, V extends IValue> Result<U> add(Result<V> that) {
    return that.addTuple(this);
  }
 
  @Override
  public Result<IValue> fieldSelect(int[] selectedFields) {
    return makeResult(type.select(selectedFields), value.select(selectedFields), ctx);
  }
 
  @Override
  public Result<IValue> fieldSelect(Field[] selectedFields) {
    int nFields = selectedFields.length;
    int fieldIndices[] = new int[nFields];
    Type baseType = this.getType();
   
    for (int i = 0; i < nFields; i++) {
      Field f = selectedFields[i];
      if (f.isIndex()) {
        fieldIndices[i] = ((IInteger) f.getFieldIndex()
            .interpret(this.ctx.getEvaluator()).getValue()).intValue();
      } else {
        String fieldName = org.rascalmpl.interpreter.utils.Names
            .name(f.getFieldName());
        try {
          fieldIndices[i] = baseType.getFieldIndex(fieldName);
        } catch (UndeclaredFieldException e) {
          throw new UndeclaredField(fieldName, baseType,
              ctx.getCurrentAST());
        }
      }

      if (fieldIndices[i] < 0 || fieldIndices[i] > baseType.getArity()) {
        throw org.rascalmpl.interpreter.utils.RuntimeExceptionFactory
            .indexOutOfBounds(ValueFactoryFactory.getValueFactory().integer(fieldIndices[i]),
                ctx.getCurrentAST(), ctx.getStackTrace());
      }
    }
   
    return this.fieldSelect(fieldIndices);
  }
 
  @Override
  public Result<IBool> has(Name name) {
    return ResultFactory.bool(getType().hasField(Names.name(name)), ctx);
  }
 
  @Override
  public <U extends IValue> Result<U> fieldAccess(String name, TypeStore store) {
      if (!getType().hasFieldNames()) {
        throw new UndeclaredField(name, getType(), ctx.getCurrentAST());
      }
     
      if (!getType().hasField(name, store)) {
        throw new UndeclaredField(name, getType(), ctx.getCurrentAST());
      }
     
      try {
        int index = getType().getFieldIndex(name);
        Type type = getType().getFieldType(index);
        return makeResult(type, getValue().get(index), ctx);
      }
      catch (UndeclaredFieldException e){
        throw new UndeclaredField(name, getType(), ctx.getCurrentAST());
      }
  }
   
  @Override
  public <U extends IValue, V extends IValue> Result<U> fieldUpdate(String name, Result<V> repl, TypeStore store) {
    if (!getType().hasFieldNames()) {
      throw new UndeclaredField(name, getType(), ctx.getCurrentAST());
    }

    try {
      int index = getType().getFieldIndex(name);
      Type type = getType().getFieldType(index);
      if(!type.isSubtypeOf(repl.getType())){
        throw new UnexpectedType(type, repl.getType(), ctx.getCurrentAST());
      }
      return makeResult(getType(), getValue().set(index, repl.getValue()), ctx);
    } catch (UndeclaredFieldException e) {
      throw new UndeclaredField(name, getType(), ctx.getCurrentAST());
    }
  }
 
  @Override
  @SuppressWarnings("unchecked")
  public <U extends IValue, V extends IValue> Result<U> subscript(Result<?>[] subscripts) {
    if (subscripts.length > 1) {
      throw new UnsupportedSubscriptArity(getType(), subscripts.length, ctx.getCurrentAST());
    }
    Result<IValue> subsBase = (Result<IValue>)subscripts[0];
    if(subsBase == null)
      /*
       * Wild card not allowed as tuple subscript
       */
      throw new UnsupportedSubscript(type, null, ctx.getCurrentAST());
    if (!subsBase.getType().isInteger()){
      throw new UnsupportedSubscript(getTypeFactory().integerType(), subsBase.getType(), ctx.getCurrentAST());
    }
    IInteger index = (IInteger)subsBase.getValue();
    int idx = index.intValue();
    if(idx < 0){
      idx = idx + getValue().arity();
    }
    if ( (idx >= getValue().arity()) || (idx < 0)) {
      throw RuntimeExceptionFactory.indexOutOfBounds(index, ctx.getCurrentAST(), ctx.getStackTrace());
    }
   
    Type elementType = getType().getFieldType(idx);
    IValue element = getValue().get(idx);
    return makeResult(elementType, element, ctx);
  }
 
  @Override
  public <V extends IValue> Result<IBool> equals(Result<V> that) {
    return that.equalToTuple(this);
  }

  @Override
  public <V extends IValue> Result<IBool> nonEquals(Result<V> that) {
    return that.nonEqualToTuple(this);
  }

  @Override
  public <V extends IValue> Result<IBool> lessThan(Result<V> result) {
    return result.lessThanTuple(this);
  }
 
  @Override
  public <V extends IValue> LessThanOrEqualResult lessThanOrEqual(Result<V> result) {
    return result.lessThanOrEqualTuple(this);
  }
 
  @Override
  public <V extends IValue> Result<IBool> greaterThan(Result<V> result) {
    return result.greaterThanTuple(this);
  }
 
  @Override
  public <V extends IValue> Result<IBool> greaterThanOrEqual(Result<V> result) {
    return result.greaterThanOrEqualTuple(this);
  }
 
  ///

  @Override
  protected <U extends IValue> Result<U> addTuple(TupleResult that) {
    // Note reversed args
    TupleResult left = that;
    TupleResult right = this;
    Type leftType = left.getType();
    Type rightType = right.getType();
   
    int leftArity = leftType.getArity();
    int rightArity = rightType.getArity();
    int newArity = leftArity + rightArity;
   
    Type fieldTypes[] = new Type[newArity];
    String fieldNames[] = new String[newArity];
    IValue fieldValues[] = new IValue[newArity];
   
    boolean consistentLabels = true;
    for(int i = 0; i < leftArity; i++){
      fieldTypes[i] = leftType.getFieldType(i);
      fieldNames[i] = leftType.getFieldName(i);
      fieldValues[i] = left.getValue().get(i);
      consistentLabels = fieldNames[i] != null;
    }
   
    for(int i = 0; i < rightArity; i++){
      fieldTypes[leftArity + i] = rightType.getFieldType(i);
      fieldNames[leftArity + i] = rightType.getFieldName(i);
      fieldValues[leftArity + i] = right.getValue().get(i);
      consistentLabels = fieldNames[i] != null;
      if (consistentLabels) {
        for (int j = 0; j < leftArity; j++) {
          if (fieldNames[j].equals(fieldNames[i])) {
            // duplicate field name, so degenerate to unlabeled tuple
            consistentLabels = false;
          }
        }
      }
    }
   
    Type newTupleType;
    if (consistentLabels) {
      newTupleType = getTypeFactory().tupleType(fieldTypes, fieldNames);
    }
    else {
      newTupleType = getTypeFactory().tupleType(fieldTypes);
    }
    return makeResult(newTupleType, getValueFactory().tuple(fieldValues), ctx);
  }
 
 
  @Override
  protected <U extends IValue> Result<U> addRelation(RelationResult that) {
    return that.insertTuple(this);
  }
 
  @Override
  protected <U extends IValue> Result<U> subtractRelation(RelationResult that) {
    if(that.getType().getElementType().getArity() == this.getType().getArity())
      return that.removeElement(this);
    return super.subtractRelation(that);
  }
 
  @Override
  protected <U extends IValue> Result<U> addListRelation(ListRelationResult that) {
    return that.appendTuple(this);
  }
   
  @Override
  protected <U extends IValue> Result<U> subtractListRelation(ListRelationResult that) {
    if(that.getType().getElementType().getArity() == this.getType().getArity())
      return that.removeElement(this);
    return super.subtractListRelation(that);
  }

 
  @Override
  protected Result<IBool> equalToTuple(TupleResult that) {
    return that.equalityBoolean(this);
  }
 
  @Override
  protected Result<IBool> nonEqualToTuple(TupleResult that) {
    return that.nonEqualityBoolean(this);
  }

  @Override
  protected Result<IBool> greaterThanOrEqualTuple(TupleResult that) {
    return that.lessThanOrEqualTuple(this);
  }
 
  @Override
  protected Result<IBool> greaterThanTuple(TupleResult that) {
    LessThanOrEqualResult loe = that.lessThanOrEqualTuple(this);
    return loe.isLess();
  }
 
  @Override
  protected Result<IBool> lessThanTuple(TupleResult that) {
    LessThanOrEqualResult loe = lessThanOrEqualTuple(that);
    return loe.isLess();
  }
 
  @Override
  protected LessThanOrEqualResult lessThanOrEqualTuple(TupleResult that) {
    ITuple left = that.getValue();
    int leftArity = left.arity();
    ITuple right = getValue();
    int rightArity = right.arity();
   
    for (int i = 0; i < Math.min(leftArity, rightArity); i++) {
       IValue leftArg = left.get(i);
       IValue rightArg = right.get(i);
       LessThanOrEqualResult loe = makeResult(leftArg.getType(), leftArg, ctx).lessThanOrEqual(makeResult(rightArg.getType(), rightArg,ctx));
      
       if (loe.getLess()) {
         return loe;
       }
      
       if (!loe.getEqual()) {
         return new LessThanOrEqualResult(false, false, ctx);
       }
    }
   
    return new LessThanOrEqualResult(leftArity < rightArity, leftArity == rightArity, ctx);
  }
}
TOP

Related Classes of org.rascalmpl.interpreter.result.TupleResult

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.