Package org.rascalmpl.interpreter

Source Code of org.rascalmpl.interpreter.AssignableEvaluator

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

import org.eclipse.imp.pdb.facts.IValue;
import org.eclipse.imp.pdb.facts.type.TypeFactory;
import org.rascalmpl.ast.AbstractAST;
import org.rascalmpl.ast.Assignable;
import org.rascalmpl.ast.Assignment;
import org.rascalmpl.interpreter.asserts.ImplementationError;
import org.rascalmpl.interpreter.env.Environment;
import org.rascalmpl.interpreter.env.GlobalEnvironment;
import org.rascalmpl.interpreter.result.Result;
import org.rascalmpl.interpreter.staticErrors.UnexpectedType;
import org.rascalmpl.interpreter.staticErrors.UninitializedVariable;


/**
* Implements assignments in their different shapes, using value lookup
* implemented by Evaluator.
* TODO: does not implement type checking completely
*/
public class AssignableEvaluator {
  public enum AssignmentOperator {Default, Addition, Subtraction, Product, Division, Intersection, IsDefined}
  private AssignmentOperator operator;
    private Result<IValue> value;
    private final Environment env;
    private final IEvaluator<Result<IValue>> eval;
  private static final TypeFactory tf = org.eclipse.imp.pdb.facts.type.TypeFactory.getInstance();
   
  public AssignableEvaluator(Environment env, Assignment operator, Result<IValue> value, IEvaluator<Result<IValue>> eval) {
    if(operator == null || operator.isDefault())
      this.__setOperator(AssignmentOperator.Default);
    else if(operator.isAddition())
      this.__setOperator(AssignmentOperator.Addition);
    else if(operator.isSubtraction())
      this.__setOperator(AssignmentOperator.Subtraction);
    else if(operator.isProduct())
      this.__setOperator(AssignmentOperator.Product);
    else if(operator.isDivision())
      this.__setOperator(AssignmentOperator.Division);
    else if(operator.isIntersection())
      this.__setOperator(AssignmentOperator.Intersection);
    else if(operator.isIfDefined())
      this.__setOperator(AssignmentOperator.IsDefined);
    else
        throw new ImplementationError("Unknown assignment operator");
    this.__setValue(value);
    this.env = env;
    this.eval = eval;
  }
 
  public void __setValue(Result<IValue> value) {
    this.value = value;
  }

  public Result<IValue> __getValue() {
    return value;
  }

  public Environment __getEnv() {
    return env;
  }

  public void __setOperator(AssignmentOperator operator) {
    this.operator = operator;
  }

  public AssignmentOperator __getOperator() {
    return operator;
  }

  public IEvaluator<Result<IValue>> __getEval() {
    return eval;
  }

  public static TypeFactory __getTf() {
    return tf;
  }

  /*
   * Given an old result and a right-hand side Result, compute a new result.
   */
  public Result<IValue> newResult(Result<IValue> oldValue, Result<IValue> rhsValue) {
    Result<IValue> newValue;
    if(oldValue != null){
      switch(this.__getOperator()){
      case Default:
        newValue = rhsValue; break;
      case Addition:
        newValue = oldValue.add(rhsValue); break;
      case Subtraction:
        newValue = oldValue.subtract(rhsValue); break;
      case Product:
        newValue = oldValue.multiply(rhsValue); break;
      case Division:
        newValue = oldValue.divide(rhsValue); break;
      case Intersection:
        newValue = oldValue.intersect(rhsValue); break;
      case IsDefined:
        return oldValue;
      default:
        throw new ImplementationError("Unknown assignment operator");
      }
   
      if (newValue.getType().isSubtypeOf(oldValue.getType())) {
        newValue = org.rascalmpl.interpreter.result.ResultFactory.makeResult(oldValue.getType(), newValue.getValue(),this.__getEval());
        return newValue;
      } else   if (oldValue.hasInferredType()) {
        // Be liberal here: if the user has not declared a variable explicitly
        // we use the lub type for the new value.
        newValue = org.rascalmpl.interpreter.result.ResultFactory.makeResult(oldValue.getType().lub(newValue.getType()), newValue.getValue(),this.__getEval());
        newValue.setInferredType(true);
        return newValue;
      }
     
      // we use rhs value here, because the addition (for example) implicitly casts up to value,
      // in which case the error is lost. Since we know that the left hand side of the addition
      // is always the variable we are updating, the cause of the error must always be in the value
      // on the right hand side
      throw new UnexpectedType(oldValue.getType(), rhsValue.getType(), this.__getEval().getCurrentAST());
    }
    switch(this.__getOperator()){
      case Default:
      case IsDefined:
        return rhsValue;
      default:
        throw new UninitializedVariable("assignment operator", this.__getEval().getCurrentAST());
    }
  }
 
  public Result<IValue> newResult(IValue oldValue, Result<IValue> rhsValue){
    if (oldValue != null){
      Result<IValue> res = org.rascalmpl.interpreter.result.ResultFactory.makeResult(oldValue.getType().lub(rhsValue.getType()), oldValue, this.__getEval());
      return this.newResult(res, rhsValue);
    }
    switch(this.__getOperator()){
    case Default:
    case IsDefined:
        return rhsValue;
    default:
      throw new UninitializedVariable("assignment operator", this.__getEval().getCurrentAST());
    }
  }
 
  public Result<IValue> recur(Assignable x, Result<IValue> result) {
    return x.getReceiver().assignment(new org.rascalmpl.interpreter.AssignableEvaluator(this.__getEnv(), null, result, this.__getEval()));
  }
 
  public AbstractAST getCurrentAST() {
    return this.__getEval().getCurrentAST();
  }

  public Environment getCurrentEnvt() {
    return this.__getEval().getCurrentEnvt();
  }

  public IEvaluator<Result<IValue>> getEvaluator() {
    return this.__getEval().getEvaluator();
  }

  public GlobalEnvironment getHeap() {
    return this.__getEval().getHeap();
  }

  public StackTrace getStackTrace() {
    return this.__getEval().getStackTrace();
  }

  public void pushEnv() {
    this.__getEval().pushEnv();   
  }

  public void runTests(IRascalMonitor monitor) {
    this.__getEval().runTests(monitor);
  }

  public void setCurrentEnvt(Environment environment) {
    this.__getEval().setCurrentEnvt(environment);
  }

  public void unwind(Environment old) {
    this.__getEval().unwind(old);
  }

}
TOP

Related Classes of org.rascalmpl.interpreter.AssignableEvaluator

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.