Package org.rascalmpl.semantics.dynamic

Source Code of org.rascalmpl.semantics.dynamic.Assignable$Variable

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

import java.util.List;
import java.util.Map;

import org.eclipse.imp.pdb.facts.IConstructor;
import org.eclipse.imp.pdb.facts.IInteger;
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.IString;
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.TypeStore;
import org.rascalmpl.ast.Expression;
import org.rascalmpl.ast.Name;
import org.rascalmpl.ast.OptionalExpression;
import org.rascalmpl.ast.QualifiedName;
import org.rascalmpl.interpreter.AssignableEvaluator;
import org.rascalmpl.interpreter.AssignableEvaluator.AssignmentOperator;
import org.rascalmpl.interpreter.Evaluator;
import org.rascalmpl.interpreter.IEvaluator;
import org.rascalmpl.interpreter.asserts.ImplementationError;
import org.rascalmpl.interpreter.control_exceptions.Throw;
import org.rascalmpl.interpreter.result.Result;
import org.rascalmpl.interpreter.result.ResultFactory;
import org.rascalmpl.interpreter.staticErrors.UndeclaredAnnotation;
import org.rascalmpl.interpreter.staticErrors.UndeclaredField;
import org.rascalmpl.interpreter.staticErrors.UndeclaredVariable;
import org.rascalmpl.interpreter.staticErrors.UnexpectedType;
import org.rascalmpl.interpreter.staticErrors.UninitializedVariable;
import org.rascalmpl.interpreter.staticErrors.UnsupportedOperation;
import org.rascalmpl.interpreter.staticErrors.UnsupportedSlice;
import org.rascalmpl.interpreter.staticErrors.UnsupportedSubscript;
import org.rascalmpl.interpreter.types.FunctionType;
import org.rascalmpl.interpreter.types.NonTerminalType;
import org.rascalmpl.interpreter.utils.Names;

public abstract class Assignable extends org.rascalmpl.ast.Assignable {

  static public class Annotation extends
      org.rascalmpl.ast.Assignable.Annotation {

    public Annotation(IConstructor __param1,
        org.rascalmpl.ast.Assignable __param2, Name __param3) {
      super(__param1, __param2, __param3);
    }

    @Override
    public Result<IValue> assignment(AssignableEvaluator __eval) {

      String label = org.rascalmpl.interpreter.utils.Names.name(this
          .getAnnotation());
      Result<IValue> result = this.getReceiver().interpret(
          (Evaluator) __eval.__getEval());

      if (result == null || result.getValue() == null) {
        throw new UninitializedVariable(label, this.getReceiver());
      }

      if (!__eval.__getEnv().declaresAnnotation(result.getType(), label)) {
        throw new UndeclaredAnnotation(label, result.getType(),
            this);
      }

      try {
        __eval.__setValue(__eval.newResult(result.getAnnotation(label,
            __eval.__getEnv()), __eval.__getValue()));
      } catch (Throw e) {
        // NoSuchAnnotation
      }
      return __eval.recur(this, result.setAnnotation(label, __eval
          .__getValue(), __eval.__getEnv()));
      // result.setValue(((IConstructor)
      // result.getValue()).setAnnotation(label, value.getValue()));
      // return recur(this, result);

    }

    @Override
    public Result<IValue> interpret(IEvaluator<Result<IValue>> __eval) {

      Result<IValue> receiver = this.getReceiver().interpret(__eval);
      String label = Names.name(this.getAnnotation());

      if (!__eval.getCurrentEnvt().declaresAnnotation(receiver.getType(),
          label)) {
        throw new UndeclaredAnnotation(label, receiver.getType(),
            this);
      }

      Type type = __eval.getCurrentEnvt().getAnnotationType(
          receiver.getType(), label);
      IValue value = ((IConstructor) receiver.getValue())
          .asAnnotatable().getAnnotation(label);

      return org.rascalmpl.interpreter.result.ResultFactory.makeResult(
          type, value, __eval);

    }

  }

  static public class Bracket extends org.rascalmpl.ast.Assignable.Bracket {

    public Bracket(IConstructor __param1, org.rascalmpl.ast.Assignable __param2) {
      super(__param1, __param2);
    }

  }

  static public class Constructor extends
      org.rascalmpl.ast.Assignable.Constructor {

    public Constructor(IConstructor __param1, Name __param2,
        List<org.rascalmpl.ast.Assignable> __param3) {
      super(__param1, __param2, __param3);
    }

    @Override
    public Result<IValue> assignment(AssignableEvaluator __eval) {

      Type valueType = __eval.__getValue().getType();

      if (!valueType.isNode() && !valueType.isAbstractData()
          && !valueType.isConstructor()) {
        throw new UnexpectedType(
            org.rascalmpl.interpreter.AssignableEvaluator.__getTf()
                .nodeType(), __eval.__getValue().getType(),
            this);
      }

      IConstructor node = (IConstructor) __eval.__getValue().getValue();
      Type nodeType = node.getType();

      if (nodeType.isAbstractData()) {
        nodeType = ((IConstructor) __eval.__getValue().getValue())
            .getConstructorType();
      }

      if (!node.getName().equals(
          org.rascalmpl.interpreter.utils.Names.name(this.getName()))) {
        throw org.rascalmpl.interpreter.utils.RuntimeExceptionFactory
            .nameMismatch(node.getName(),
                org.rascalmpl.interpreter.utils.Names.name(this
                    .getName()), this.getName(), __eval
                    .__getEval().getStackTrace());
      }

      List<org.rascalmpl.ast.Assignable> arguments = this.getArguments();

      if (node.arity() != arguments.size()) {
        throw org.rascalmpl.interpreter.utils.RuntimeExceptionFactory
            .arityMismatch(node.arity(), arguments.size(), this,
                __eval.__getEval().getStackTrace());
      }

      IValue[] results = new IValue[arguments.size()];
      Type[] resultTypes = new Type[arguments.size()];

      for (int i = 0; i < arguments.size(); i++) {
        Type argType = !nodeType.isConstructor() ? org.rascalmpl.interpreter.AssignableEvaluator
            .__getTf().valueType()
            : nodeType.getFieldType(i);
        IValue arg = node.get(i);
        Result<IValue> result = org.rascalmpl.interpreter.result.ResultFactory
            .makeResult(argType, arg, __eval.__getEval());
        AssignableEvaluator ae = new AssignableEvaluator(__eval
            .__getEnv(), null, result, __eval.__getEval());
        Result<IValue> argResult = arguments.get(i).assignment(ae);
        results[i] = argResult.getValue();
        resultTypes[i] = argType;
      }
     
      if (!nodeType.isAbstractData() && !nodeType.isConstructor()) {
        // TODO: can this be the case?
        return org.rascalmpl.interpreter.result.ResultFactory
            .makeResult(nodeType, __eval.__getEval()
                .getValueFactory().node(node.getName(), results),
                __eval.__getEval());
      }

      Type constructor = __eval.__getEval().getCurrentEnvt()
          .getConstructor(
              node.getName(),
              org.rascalmpl.interpreter.AssignableEvaluator
                  .__getTf().tupleType(resultTypes));

      if (constructor == null) {
        throw new ImplementationError("could not find constructor for "
            + node.getName()
            + " : "
            + org.rascalmpl.interpreter.AssignableEvaluator
                .__getTf().tupleType(resultTypes));
      }

      return org.rascalmpl.interpreter.result.ResultFactory.makeResult(
          constructor.getAbstractDataType(), __eval.__getEval().getValueFactory().constructor(constructor, results), __eval
              .__getEval());

    }

    @Override
    public Result<IValue> interpret(IEvaluator<Result<IValue>> __eval) {

      throw new ImplementationError(
          "Constructor assignable does not represent a value");

    }

  }

  static public class FieldAccess extends
      org.rascalmpl.ast.Assignable.FieldAccess {

    public FieldAccess(IConstructor __param1,
        org.rascalmpl.ast.Assignable __param2, Name __param3) {
      super(__param1, __param2, __param3);
    }

    @Override
    public Result<IValue> assignment(AssignableEvaluator __eval) {

      Result<IValue> receiver = this.getReceiver().interpret(
          (Evaluator) __eval.__getEval());
      String label = org.rascalmpl.interpreter.utils.Names.name(this.getField());

      if (receiver == null || receiver.getValue() == null) {
        throw new UninitializedVariable(label, this.getReceiver());
      }

      if (receiver.getType().isTuple()) {

        int idx = receiver.getType().getFieldIndex(label);
        if (idx < 0) {
          throw new UndeclaredField(label, receiver.getType(), this);
        }

        __eval.__setValue(__eval.newResult(((ITuple) receiver
            .getValue()).get(idx), __eval.__getValue()));
        IValue result = ((ITuple) receiver.getValue()).set(idx, __eval
            .__getValue().getValue());
        return __eval.recur(this,
            org.rascalmpl.interpreter.result.ResultFactory
            .makeResult(receiver.getType(), result, __eval
                .__getEval()));
      }
      else if (receiver.getType() instanceof NonTerminalType) {
        Result<IValue> result = receiver.fieldUpdate(label, __eval.__getValue(), __eval.getCurrentEnvt().getStore());

        __eval.__setValue(__eval.newResult(receiver.fieldAccess(label, __eval.getCurrentEnvt().getStore()), __eval
            .__getValue()));

        if (!result.getType().isSubtypeOf(receiver.getType())) {
          throw new UnexpectedType(receiver.getType(), result.getType(), __eval.getCurrentAST());
        }
        return __eval.recur(this, result);
      }
      else if (receiver.getType().isConstructor()
          || receiver.getType().isAbstractData()) {
        IConstructor cons = (IConstructor) receiver.getValue();
        Type node = cons.getConstructorType();

        if (node.hasField(label)) {
          int index = node.getFieldIndex(label);

          if (!__eval.__getValue().getType().isSubtypeOf(
              node.getFieldType(index))) {
            throw new UnexpectedType(node.getFieldType(index),
                __eval.__getValue().getType(), this);
          }
          __eval.__setValue(__eval.newResult(cons.get(index), __eval
              .__getValue()));

          IValue result = cons.set(index, __eval.__getValue().getValue());
          return __eval.recur(this,
              org.rascalmpl.interpreter.result.ResultFactory
              .makeResult(receiver.getType(), result, __eval
                  .__getEval()));
        }
        else if (node.hasKeywordParameter(label)) {
          if (!__eval.__getValue().getType().isSubtypeOf(
              node.getKeywordParameterType(label))) {
            throw new UnexpectedType(node.getKeywordParameterType(label),
                __eval.__getValue().getType(), this);
          }

          __eval.__setValue(__eval.newResult(cons.asWithKeywordParameters().getParameter(label), __eval.__getValue()));

          IValue result = cons.asWithKeywordParameters().setParameter(label,  __eval.__getValue().getValue());
          return __eval.recur(this,
              org.rascalmpl.interpreter.result.ResultFactory
              .makeResult(receiver.getType(), result, __eval
                  .__getEval()));
        }
        else {
          throw new UndeclaredField(label, receiver.getValue().getType(), this);
        }

      } else if (receiver.getType().isSourceLocation()) {
        // ISourceLocation loc = (ISourceLocation) receiver.getValue();

        __eval.__setValue(__eval.newResult(receiver.fieldAccess(label,
            __eval.__getEnv().getStore()), __eval.__getValue()));
        return __eval.recur(this, receiver.fieldUpdate(label, __eval
            .__getValue(), __eval.__getEnv().getStore()));
        // return recur(this, eval.sourceLocationFieldUpdate(loc, label,
        // value.getValue(), value.getType(), this));
      } else if (receiver.getType().isDateTime()) {
        __eval.__setValue(__eval.newResult(receiver.fieldAccess(label,
            __eval.__getEnv().getStore()), __eval.__getValue()));
        return __eval.recur(this, receiver.fieldUpdate(label, __eval
            .__getValue(), __eval.__getEnv().getStore()));
      } else {
        throw new UndeclaredField(label, receiver.getType(), this);
      }

    }

    @Override
    public Result<IValue> interpret(IEvaluator<Result<IValue>> __eval) {

      Result<IValue> receiver = this.getReceiver().interpret(__eval);
      String label = org.rascalmpl.interpreter.utils.Names.name(this
          .getField());

      if (receiver == null || receiver.getValue() == null) {
        // TODO: can this ever happen?
        throw new UndeclaredVariable(label, this.getReceiver());
      }

      Type receiverType = receiver.getType();
      if (receiverType.isTuple()) {
        // the run-time tuple may not have labels, the static type can
        // have labels,
        // so we use the static type here.
        int index = receiverType.getFieldIndex(label);
        IValue result = ((ITuple) receiver.getValue()).get(index);
        Type type = receiverType.getFieldType(index);
        return org.rascalmpl.interpreter.result.ResultFactory
            .makeResult(type, result, __eval);
      }
      else if (receiverType.isExternalType() && receiverType instanceof NonTerminalType) {
        return receiver.fieldAccess(label, __eval.getCurrentEnvt().getStore());
      }
      else if (receiverType.isConstructor() || receiverType.isAbstractData()) {
        IConstructor cons = (IConstructor) receiver.getValue();
        Type node = cons.getConstructorType();

        if (!receiverType.hasField(label, __eval.getCurrentEnvt()
            .getStore())
            && !receiverType.hasKeywordParameter(label, __eval.getCurrentEnvt().getStore())) {
          throw new UndeclaredField(label, receiverType, this);
        }

        if (!node.hasField(label) && ! node.hasKeywordParameter(label)) {
          throw org.rascalmpl.interpreter.utils.RuntimeExceptionFactory
              .noSuchField(label, this, __eval.getStackTrace());
        }

        if (node.hasKeywordParameter(label)) {
          return ResultFactory
              .makeResult(node.getKeywordParameterType(label), cons.asWithKeywordParameters().getParameter(label)
                  ,__eval);
        }
        else {
          int index = node.getFieldIndex(label);
          return ResultFactory
              .makeResult(node.getFieldType(index), cons.get(index),
                  __eval);
        }
      } else if (receiverType.isSourceLocation()) {
        return receiver.fieldAccess(label, new TypeStore());
      } else {
        throw new UndeclaredField(label, receiverType, this);
      }

    }

  }

  static public class IfDefinedOrDefault extends
      org.rascalmpl.ast.Assignable.IfDefinedOrDefault {

    public IfDefinedOrDefault(IConstructor __param1,
        org.rascalmpl.ast.Assignable __param2, Expression __param3) {
      super(__param1, __param2, __param3);
    }

    @Override
    public Result<IValue> assignment(AssignableEvaluator __eval) {

      try {
        this.getReceiver().interpret((Evaluator) __eval.__getEval()); // notice
        // we
        // use
        // 'eval'
        // here
        // not
        // '__eval'
        // if it was not defined, __eval would have thrown an exception,
        // so now we can just go on
        return this.getReceiver().assignment(__eval);
      } catch (Throw e) {
        __eval.__setValue(__eval.newResult(this.getDefaultExpression()
            .interpret((Evaluator) __eval.__getEval()), __eval
            .__getValue()));
        __eval.__setOperator(AssignmentOperator.Default);
        return this.getReceiver().assignment(__eval);
      }

    }

    @Override
    public Result<IValue> interpret(IEvaluator<Result<IValue>> __eval) {

      throw new ImplementationError(
          "ifdefined assignable does not represent a value");

    }

  }

  static public class Subscript extends
      org.rascalmpl.ast.Assignable.Subscript {

    public Subscript(IConstructor __param1, org.rascalmpl.ast.Assignable __param2,
        Expression __param3) {
      super(__param1, __param2, __param3);
    }

    @Override
    public Result<IValue> assignment(AssignableEvaluator __eval) {

      Result<IValue> rec = this.getReceiver().interpret(
          (Evaluator) __eval.__getEval());
      Result<IValue> subscript = this.getSubscript().interpret(
          (Evaluator) __eval.__getEval());
      Result<IValue> result;

      if (rec == null || rec.getValue() == null) {
        throw new UninitializedVariable(this.getReceiver());
      }

      if (rec.getType().isList()
          && subscript.getType().isInteger()) {
        try {
          IList list = (IList) rec.getValue();
          int index = ((IInteger) subscript.getValue()).intValue();
          __eval.__setValue(__eval.newResult(list.get(index), __eval
              .__getValue()));
          list = list.put(index, __eval.__getValue().getValue());
          result = org.rascalmpl.interpreter.result.ResultFactory
              .makeResult(rec.hasInferredType() ? rec.getType()
                  .lub(list.getType()) : rec.getType(), list,
                  __eval.__getEval());
        } catch (IndexOutOfBoundsException e) {
          throw org.rascalmpl.interpreter.utils.RuntimeExceptionFactory
              .indexOutOfBounds((IInteger) subscript.getValue(),
                  __eval.__getEval().getCurrentAST(), __eval
                      .__getEval().getStackTrace());
        }
      } else if (rec.getType().isMap()) {
        Type keyType = rec.getType().getKeyType();

        if (rec.hasInferredType()
            || subscript.getType().isSubtypeOf(keyType)) {
          IValue oldValue = ((IMap) rec.getValue()).get(subscript
              .getValue());
          __eval.__setValue(__eval.newResult(oldValue, __eval
              .__getValue()));
          IMap map = ((IMap) rec.getValue()).put(
              subscript.getValue(), __eval.__getValue()
                  .getValue());
          result = org.rascalmpl.interpreter.result.ResultFactory
              .makeResult(rec.hasInferredType() ? rec.getType()
                  .lub(map.getType()) : rec.getType(), map,
                  __eval.__getEval());
        } else {
          throw new UnexpectedType(keyType, subscript.getType(),
              this.getSubscript());
        }

      } else if (rec.getType().isNode()
          && subscript.getType().isInteger()) {
        int index = ((IInteger) subscript.getValue()).intValue();
        IConstructor node = (IConstructor) rec.getValue();

        if (index >= node.arity()) {
          throw org.rascalmpl.interpreter.utils.RuntimeExceptionFactory
              .indexOutOfBounds((IInteger) subscript.getValue(),
                  __eval.__getEval().getCurrentAST(), __eval
                      .__getEval().getStackTrace());
        }
        __eval.__setValue(__eval.newResult(node.get(index), __eval
            .__getValue()));
        node = node.set(index, __eval.__getValue().getValue());
        result = org.rascalmpl.interpreter.result.ResultFactory
            .makeResult(rec.getType(), node, __eval.__getEval());
      } else if (rec.getType().isTuple()
          && subscript.getType().isInteger()) {
        int index = ((IInteger) subscript.getValue()).intValue();
        ITuple tuple = (ITuple) rec.getValue();

        if (index >= tuple.arity()) {
          throw org.rascalmpl.interpreter.utils.RuntimeExceptionFactory
              .indexOutOfBounds((IInteger) subscript.getValue(),
                  __eval.__getEval().getCurrentAST(), __eval
                      .__getEval().getStackTrace());
        }

        __eval.__setValue(__eval.newResult(tuple.get(index), __eval
            .__getValue()));

        tuple = tuple.set(index, __eval.__getValue().getValue());
        result = org.rascalmpl.interpreter.result.ResultFactory
            .makeResult(rec.getType(), tuple, __eval.__getEval());
      } else if (rec.getType().isRelation()
          && subscript.getType().isSubtypeOf(
              rec.getType().getFieldType(0))) {
        ISet rel = (ISet) rec.getValue();
        IValue sub = subscript.getValue();

        if (rec.getType().getArity() != 2) {
          throw new UnsupportedSubscript(rec.getType(),
              subscript.getType(), this);
        }

        if (!__eval.__getValue().getType().isSubtypeOf(
            rec.getType().getFieldType(1))) {
          throw new UnexpectedType(
              rec.getType().getFieldType(1), __eval.__getValue()
                  .getType(), __eval.__getEval()
                  .getCurrentAST());
        }

        rel = rel.insert(__eval.__getEval().getValueFactory().tuple(
            sub, __eval.__getValue().getValue()));
        result = org.rascalmpl.interpreter.result.ResultFactory
            .makeResult(rec.getType(), rel, __eval.__getEval());
      } else {
        throw new UnsupportedSubscript(rec.getType(), subscript
            .getType(), this);
        // TODO implement other subscripts
      }

      return __eval.recur(this, result);

    }
   
    /**
     * Return an evaluation result that is already in normal form, i.e., all
     * potential rules have already been applied to it.
     */
    private Result<IValue> normalizedResult(IEvaluator<Result<IValue>> __eval, Type t, IValue v) {
      Map<Type, Type> bindings = __eval.getCurrentEnvt().getTypeBindings();
      Type instance;

      if (bindings.size() > 0) {
        instance = t.instantiate(bindings);
      } else {
        instance = t;
      }

      if (v != null) {
        checkType(v.getType(), instance);
      }
      return org.rascalmpl.interpreter.result.ResultFactory.makeResult(instance, v, __eval);
    }
   
    private void checkType(Type given, Type expected) {
      if (expected instanceof FunctionType) {
        return;
      }
      if (!given.isSubtypeOf(expected)) {
        throw new UnexpectedType(expected, given, this);
      }
    }

    @Override
    public Result<IValue> interpret(IEvaluator<Result<IValue>> __eval) {

      Result<IValue> receiver = this.getReceiver().interpret(__eval);
      Result<IValue> subscript = this.getSubscript().interpret(__eval);

      assert receiver != null && receiver.getValue() != null;
     
      if (receiver.getType().isList()) {
        if (subscript.getType().isInteger()) {
          IList list = (IList) receiver.getValue();
          IValue result = list.get(((IInteger) subscript.getValue())
              .intValue());
          Type type = receiver.getType().getElementType();
          return normalizedResult(__eval, type, result);
        }

        throw new UnexpectedType(
            org.rascalmpl.interpreter.Evaluator.__getTf()
                .integerType(), subscript.getType(), this);
      } else if (receiver.getType().isMap()) {
        Type keyType = receiver.getType().getKeyType();

        if (receiver.hasInferredType()
            || subscript.getType().isSubtypeOf(keyType)) {
          IValue result = ((IMap) receiver.getValue()).get(subscript
              .getValue());

          if (result == null) {
            throw org.rascalmpl.interpreter.utils.RuntimeExceptionFactory
                .noSuchKey(subscript.getValue(), this, __eval
                    .getStackTrace());
          }
          Type type = receiver.getType().getValueType();
          return org.rascalmpl.interpreter.result.ResultFactory
              .makeResult(type, result, __eval);
        }

        throw new UnexpectedType(keyType, subscript.getType(),
            this.getSubscript());
      }
      // TODO implement other subscripts
      throw new UnsupportedOperation("subscript",
          receiver.getType(), this);

    }

  }
 
  static public class Slice extends
  org.rascalmpl.ast.Assignable.Slice {

    public Slice(IConstructor __param1, org.rascalmpl.ast.Assignable __param2,
        OptionalExpression __param3, OptionalExpression __param4) {
      super(__param1, __param2, __param3, __param4);
    }

    @Override
    public Result<IValue> assignment(AssignableEvaluator __eval) {

      Result<IValue> rec = this.getReceiver().interpret(
          (Evaluator) __eval.__getEval());
      Result<IValue> first = null;
      if(this.getOptFirst().hasExpression()){
        first = this.getOptFirst().getExpression().interpret(
          (Evaluator) __eval.__getEval());
      }
      Result<IValue> end = null;
      if(this.getOptLast().hasExpression()){
        end = this.getOptLast().getExpression().interpret(
          (Evaluator) __eval.__getEval());
      }
      Result<IValue> result;

      assert rec != null && rec.getValue() != null;
     
      if( !(first == null || first.getType().isInteger()) ){
        throw new UnsupportedSubscript(rec.getType(), first.getType(), this);
      }
         
      if( !(end == null || end.getType().isInteger()) ){
        throw new UnsupportedSubscript(rec.getType(), end.getType(), this);
      }
      int len =  rec.getType().isList() ? ((IList) rec.getValue()).length()
           : rec.getType().isString() ? ((IString) rec.getValue()).length()
           : rec.getType().isNode() ?((INode) rec.getValue()).arity()
           : 0 ;

      int firstIndex = 0;
      int secondIndex = 1;
      int endIndex = len;

      if(first != null){
        firstIndex = ((IInteger) first.getValue()).intValue();
        if(firstIndex < 0)
          firstIndex += len;
      }

      if(end != null){
        endIndex =  ((IInteger) end.getValue()).intValue();
        if(endIndex < 0){
          endIndex += len;
        }
      }

      secondIndex = firstIndex <= endIndex ? firstIndex + 1 : firstIndex - 1;

      if (rec.getType().isList()) {
        try {
          IList list = (IList) rec.getValue();
         
          IValue repl = __eval.__getValue().getValue();
          if(!repl.getType().isList()){
            throw new UnexpectedType(rec.getType(), repl.getType(), __eval.__getEval().getCurrentAST());
          }
         
          __eval.__setValue(__eval.newResult(list, __eval.__getValue()));
          list = list.replace(firstIndex, secondIndex, endIndex, (IList) repl);
         
          result = org.rascalmpl.interpreter.result.ResultFactory
              .makeResult(rec.hasInferredType() ? rec.getType()
                  .lub(list.getType()) : rec.getType(), list,
                  __eval.__getEval());
        } catch (IndexOutOfBoundsException e) { // include last in message
          throw org.rascalmpl.interpreter.utils.RuntimeExceptionFactory
          .indexOutOfBounds((IInteger) first.getValue(),
              __eval.__getEval().getCurrentAST(), __eval
              .__getEval().getStackTrace());
        }
      } else if (rec.getType().isString()) {
        try {
          IString str = (IString) rec.getValue();
         
          IValue repl = __eval.__getValue().getValue();
          if(!repl.getType().isString()){
            throw new UnexpectedType(rec.getType(), repl.getType(), __eval.__getEval().getCurrentAST());
          }
         
          __eval.__setValue(__eval.newResult(str, __eval.__getValue()));
          str = str.replace(firstIndex, secondIndex, endIndex, (IString) repl);
         
          result = org.rascalmpl.interpreter.result.ResultFactory
              .makeResult(rec.hasInferredType() ? rec.getType()
                  .lub(str.getType()) : rec.getType(), str,
                  __eval.__getEval());
        } catch (IndexOutOfBoundsException e) { // include last in message
          throw org.rascalmpl.interpreter.utils.RuntimeExceptionFactory
          .indexOutOfBounds((IInteger) first.getValue(),
              __eval.__getEval().getCurrentAST(), __eval
              .__getEval().getStackTrace());
        }
      } else if (rec.getType().isNode()) {

        try {
          INode node = (INode) rec.getValue();

          IValue repl = __eval.__getValue().getValue();
          if(!repl.getType().isList()){
            throw new UnexpectedType(rec.getType(), repl.getType(), __eval.__getEval().getCurrentAST());
          }

          __eval.__setValue(__eval.newResult(node, __eval.__getValue()));
          node = node.replace(firstIndex, secondIndex, endIndex, (IList) repl);

          result = org.rascalmpl.interpreter.result.ResultFactory
              .makeResult(rec.hasInferredType() ? rec.getType()
                  .lub(node.getType()) : rec.getType(), node,
                  __eval.__getEval());
        } catch (IndexOutOfBoundsException e) { // include last in message
          throw org.rascalmpl.interpreter.utils.RuntimeExceptionFactory
          .indexOutOfBounds((IInteger) first.getValue(),
              __eval.__getEval().getCurrentAST(), __eval
              .__getEval().getStackTrace());
        }
      } else {
        throw new UnsupportedSlice(rec.getType(), this);
        // TODO implement other slices
      }

      return __eval.recur(this, result);
    }
  }
 
  static public class SliceStep extends
  org.rascalmpl.ast.Assignable.SliceStep {

    public SliceStep(IConstructor __param1, org.rascalmpl.ast.Assignable __param2,
        OptionalExpression __param3, Expression __param4, OptionalExpression __param5) {
      super(__param1, __param2, __param3, __param4, __param5);
    }

    @Override
    public Result<IValue> assignment(AssignableEvaluator __eval) {

      Result<IValue> rec = this.getReceiver().interpret(
          (Evaluator) __eval.__getEval());
      Result<IValue> first = null;
      if(this.getOptFirst().hasExpression()){
        first = this.getOptFirst().getExpression().interpret(
          (Evaluator) __eval.__getEval());
      }
      Result<IValue> second = this.getSecond().interpret((Evaluator) __eval.__getEval());
      Result<IValue> end = null;
      if(this.getOptLast().hasExpression()){
        end = this.getOptLast().getExpression().interpret(
          (Evaluator) __eval.__getEval());
      }
      Result<IValue> result;

      assert rec != null && rec.getValue() != null;
     
      if( !(first == null || first.getType().isInteger()) ){
        throw new UnsupportedSubscript(rec.getType(), first.getType(), this);
      }
     
      if(!second.getType().isInteger()){
        throw new UnsupportedSubscript(rec.getType(), second.getType(), this);
      }
         
      if( !(end == null || end.getType().isInteger()) ){
        throw new UnsupportedSubscript(rec.getType(), end.getType(), this);
      }
     
      int len = rec.getType().isList() ? ((IList) rec.getValue()).length()
           : rec.getType().isString() ? ((IString) rec.getValue()).length()
           :  rec.getType().isNode() ?((INode) rec.getValue()).arity()
           : 0 ;

      int firstIndex = 0;
      int secondIndex = 1;
      int endIndex = len;

      if(first != null){
        firstIndex = ((IInteger) first.getValue()).intValue();
        if(firstIndex < 0)
          firstIndex += len;
      }

      if(end != null){
        endIndex =  ((IInteger) end.getValue()).intValue();
        if(endIndex < 0){
          endIndex += len;
        }
      }

      secondIndex = ((IInteger)second.getValue()).intValue();
      if(secondIndex < 0)
        secondIndex += len;

      if(!(first == null && end == null)){
        if(first == null && secondIndex > endIndex)
          firstIndex = len - 1;
        if(end == null && secondIndex < firstIndex)
          endIndex = -1;
      }

      if (rec.getType().isList()) {
        try {
          IList list = (IList) rec.getValue();         
         
          IValue repl = __eval.__getValue().getValue();
          if(!repl.getType().isList()){
            throw new UnexpectedType(rec.getType(), repl.getType(), __eval.__getEval().getCurrentAST());
          }
         
          __eval.__setValue(__eval.newResult(list, __eval.__getValue()));         
          list = list.replace(firstIndex, secondIndex, endIndex, (IList) repl);
         
          result = org.rascalmpl.interpreter.result.ResultFactory
              .makeResult(rec.hasInferredType() ? rec.getType()
                  .lub(list.getType()) : rec.getType(), list,
                  __eval.__getEval());
        } catch (IndexOutOfBoundsException e) { // include last in message
          throw org.rascalmpl.interpreter.utils.RuntimeExceptionFactory
          .indexOutOfBounds((IInteger) first.getValue(),
              __eval.__getEval().getCurrentAST(), __eval
              .__getEval().getStackTrace());
        }
      } else if (rec.getType().isString()) {
        try {
          IString str = (IString) rec.getValue();

          IValue repl = __eval.__getValue().getValue();
          if(!repl.getType().isString()){
            throw new UnexpectedType(rec.getType(), repl.getType(), __eval.__getEval().getCurrentAST());
          }
         
          __eval.__setValue(__eval.newResult(str, __eval.__getValue()));
          str = str.replace(firstIndex, secondIndex, endIndex, (IString) repl);
         
          result = org.rascalmpl.interpreter.result.ResultFactory
              .makeResult(rec.hasInferredType() ? rec.getType()
                  .lub(str.getType()) : rec.getType(), str,
                  __eval.__getEval());
        } catch (IndexOutOfBoundsException e) { // include last in message
          throw org.rascalmpl.interpreter.utils.RuntimeExceptionFactory
          .indexOutOfBounds((IInteger) first.getValue(),
              __eval.__getEval().getCurrentAST(), __eval
              .__getEval().getStackTrace());
        }
       
      } else if (rec.getType().isNode()) {

        try {
          INode node = (INode) rec.getValue();

          IValue repl = __eval.__getValue().getValue();
          if(!repl.getType().isList()){
            throw new UnexpectedType(rec.getType(), repl.getType(), __eval.__getEval().getCurrentAST());
          }

          __eval.__setValue(__eval.newResult(node, __eval.__getValue()));
          node = node.replace(firstIndex, secondIndex, endIndex, (IList) repl);

          result = org.rascalmpl.interpreter.result.ResultFactory
              .makeResult(rec.hasInferredType() ? rec.getType()
                  .lub(node.getType()) : rec.getType(), node,
                  __eval.__getEval());
        } catch (IndexOutOfBoundsException e) { // include last in message
          throw org.rascalmpl.interpreter.utils.RuntimeExceptionFactory
          .indexOutOfBounds((IInteger) first.getValue(),
              __eval.__getEval().getCurrentAST(), __eval
              .__getEval().getStackTrace());
        }
      } else {
        throw new UnsupportedSlice(rec.getType(), this);
        // TODO implement other slices
      }

      return __eval.recur(this, result);
    }

  }

  static public class Tuple extends org.rascalmpl.ast.Assignable.Tuple {

    public Tuple(IConstructor __param1, List<org.rascalmpl.ast.Assignable> __param2) {
      super(__param1, __param2);
    }

    @Override
    public Result<IValue> assignment(AssignableEvaluator __eval) {

      List<org.rascalmpl.ast.Assignable> arguments = this.getElements();

      if (!__eval.__getValue().getType().isTuple()) {
        // TODO construct a better expected type
        throw new UnexpectedType(
            org.rascalmpl.interpreter.AssignableEvaluator.__getTf()
                .tupleEmpty(), __eval.__getValue().getType(),
            this);
      }

      Type tupleType = __eval.__getValue().getType();
      ITuple tuple = (ITuple) __eval.__getValue().getValue();
      IValue[] results = new IValue[arguments.size()];
      Type[] resultTypes = new Type[arguments.size()];

      for (int i = 0; i < arguments.size(); i++) {
        Type argType = tupleType.getFieldType(i);
        IValue arg = tuple.get(i);
        Result<IValue> result = org.rascalmpl.interpreter.result.ResultFactory
            .makeResult(argType, arg, __eval.__getEval());
        AssignableEvaluator ae = new AssignableEvaluator(__eval
            .__getEnv(), null, result, __eval.__getEval());
        Result<IValue> argResult = arguments.get(i).assignment(ae);
        results[i] = argResult.getValue();
        resultTypes[i] = argResult.getType();
      }

      return org.rascalmpl.interpreter.result.ResultFactory.makeResult(
          org.rascalmpl.interpreter.AssignableEvaluator.__getTf()
              .tupleType(resultTypes), __eval
              .__getEval().getValueFactory().tuple(results), __eval
              .__getEval());

    }

    @Override
    public Result<IValue> interpret(IEvaluator<Result<IValue>> __eval) {

      throw new ImplementationError(
          "Tuple in assignable does not represent a value:" + this);

    }

  }

  static public class Variable extends org.rascalmpl.ast.Assignable.Variable {

    public Variable(IConstructor __param1, QualifiedName __param2) {
      super(__param1, __param2);
    }

    @Override
    public Result<IValue> assignment(AssignableEvaluator __eval) {

      QualifiedName qname = this.getQualifiedName();
      Result<IValue> previous = __eval.__getEnv().getVariable(qname);

      if (previous != null && previous.getValue() != null) {
        __eval.__setValue(__eval.newResult(previous, __eval
            .__getValue()));
        __eval.__getEnv().storeVariable(qname, __eval.__getValue());
        return __eval.__getValue();
      }

      switch (__eval.__getOperator()) {
      case Default:
      case IsDefined:
        __eval.__getEnv().storeVariable(qname, __eval.__getValue());
        return __eval.__getValue();
      default:
        throw new UninitializedVariable(Names.fullName(qname), this);
      }

      // TODO implement semantics of global keyword, when not given the
      // variable should be inserted in the local scope.

    }

    @Override
    public Result<IValue> interpret(IEvaluator<Result<IValue>> __eval) {

      return __eval.getCurrentEnvt().getSimpleVariable(this.getQualifiedName());

    }

  }

  public Assignable(IConstructor __param1) {
    super(__param1);
  }
}
TOP

Related Classes of org.rascalmpl.semantics.dynamic.Assignable$Variable

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.