Package org.rascalmpl.semantics.dynamic

Source Code of org.rascalmpl.semantics.dynamic.Statement$Throw

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

import java.util.List;
import java.util.Stack;

import org.eclipse.imp.pdb.facts.IConstructor;
import org.eclipse.imp.pdb.facts.IInteger;
import org.eclipse.imp.pdb.facts.IString;
import org.eclipse.imp.pdb.facts.IValue;
import org.rascalmpl.ast.Assignable;
import org.rascalmpl.ast.Bound;
import org.rascalmpl.ast.Case;
import org.rascalmpl.ast.Catch;
import org.rascalmpl.ast.DataTarget;
import org.rascalmpl.ast.Label;
import org.rascalmpl.ast.LocalVariableDeclaration;
import org.rascalmpl.ast.QualifiedName;
import org.rascalmpl.ast.Target;
import org.rascalmpl.ast.Type;
import org.rascalmpl.interpreter.Accumulator;
import org.rascalmpl.interpreter.AssignableEvaluator;
import org.rascalmpl.interpreter.IEvaluator;
import org.rascalmpl.interpreter.asserts.NotYetImplemented;
import org.rascalmpl.interpreter.control_exceptions.BreakException;
import org.rascalmpl.interpreter.control_exceptions.ContinueException;
import org.rascalmpl.interpreter.control_exceptions.Failure;
import org.rascalmpl.interpreter.control_exceptions.Filtered;
import org.rascalmpl.interpreter.control_exceptions.InterruptException;
import org.rascalmpl.interpreter.env.Environment;
import org.rascalmpl.interpreter.matching.IBooleanResult;
import org.rascalmpl.interpreter.result.Result;
import org.rascalmpl.interpreter.result.ResultFactory;
import org.rascalmpl.interpreter.staticErrors.UndeclaredVariable;
import org.rascalmpl.interpreter.staticErrors.UnexpectedType;
import org.rascalmpl.interpreter.staticErrors.UnguardedAppend;
import org.rascalmpl.interpreter.staticErrors.UninitializedVariable;
import org.rascalmpl.interpreter.utils.Cases;
import org.rascalmpl.interpreter.utils.Cases.CaseBlock;
import org.rascalmpl.interpreter.utils.Names;

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

  static public class Append extends org.rascalmpl.ast.Statement.Append {
    public Append(IConstructor node, DataTarget __param2,
        org.rascalmpl.ast.Statement __param3) {
      super(node, __param2, __param3);
    }
   
    protected Accumulator getTarget(IEvaluator<Result<IValue>> __eval) {
      if (__eval.__getAccumulators().empty()) {
        throw new UnguardedAppend(this);
      }
      if (!this.getDataTarget().isEmpty()) {
        String label = org.rascalmpl.interpreter.utils.Names.name(this.getDataTarget().getLabel());
        Accumulator accu = findDataTarget(__eval, label);
        if (accu == null) {
          throw new UnguardedAppend(this); // TODO: better error
        }
        return accu;
      }
      return __eval.__getAccumulators().peek();
    }

    private Accumulator findDataTarget(IEvaluator<Result<IValue>> __eval,
        String label) {
      Stack<Accumulator> accus = __eval.__getAccumulators();
     
      // Search backwards, to allow nested fors with same label.
      for (int i = accus.size() - 1; i >= 0; i--) {
        Accumulator accu = accus.get(i);
        if (accu.hasLabel(label)) {
          return accu;
        }
      }
      return null;
    }
   
    @Override
    public Result<IValue> interpret(IEvaluator<Result<IValue>> __eval) {

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);
     
      Accumulator target = null;
      if (__eval.__getAccumulators().empty()) {
        throw new UnguardedAppend(this);
      }
      if (!this.getDataTarget().isEmpty()) {
        String label = org.rascalmpl.interpreter.utils.Names.name(this
            .getDataTarget().getLabel());
        target = findDataTarget(__eval, label);
        if (target == null) {
          throw new UnguardedAppend(this); // TODO: better error
          // message
        }
      } else {
        target = __eval.__getAccumulators().peek();
      }
      Result<IValue> result = this.getStatement().interpret(__eval);
      target.append(result);
      return result;

    }

  }

  static public class Assert extends org.rascalmpl.ast.Statement.Assert {

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

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);
     
      Result<IValue> r = this.getExpression().interpret(__eval);
      if (!r.getType().equals(
          org.rascalmpl.interpreter.Evaluator.__getTf().boolType())) {
        throw new UnexpectedType(
            org.rascalmpl.interpreter.Evaluator.__getTf()
                .boolType(), r.getType(), this);
      }

      if (r.getValue().isEqual(__eval.__getVf().bool(false))) {
        throw org.rascalmpl.interpreter.utils.RuntimeExceptionFactory
            .assertionFailed(this, __eval.getStackTrace());
      }
      return r;

    }

  }

  static public class AssertWithMessage extends
      org.rascalmpl.ast.Statement.AssertWithMessage {

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

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);

      Result<IValue> r = this.getExpression().interpret(__eval);
      if (!r.getType().equals(
          org.rascalmpl.interpreter.Evaluator.__getTf().boolType())) {
        throw new UnexpectedType(
            org.rascalmpl.interpreter.Evaluator.__getTf()
                .boolType(), r.getType(), this);
      }
      if (r.getValue().isEqual(__eval.__getVf().bool(false))) {
        Result<IValue> msgValue = this.getMessage().interpret(__eval);
//        IString msg = __eval.__getVf().string(
//            org.rascalmpl.interpreter.utils.StringUtils.unescapeBase(msgValue.getValue().toString());
        throw org.rascalmpl.interpreter.utils.RuntimeExceptionFactory
            .assertionFailed((IString) msgValue.getValue(), __eval.getCurrentAST(), __eval
                .getStackTrace());
      }
      return r;

    }

  }

  static public class Assignment extends
      org.rascalmpl.ast.Statement.Assignment {

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

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);

     
      Result<IValue> right = this.getStatement().interpret(__eval);
//      if(this.getAssignable().isSlice() && !this.getOperator().isDefault()){
//        throw new UnsupportedOperation("Slicing assignment only implemented for simple assignment operator (=)", __eval.getCurrentAST());
//      }
      return this.getAssignable().assignment(
          new AssignableEvaluator(__eval.getCurrentEnvt(), this
              .getOperator(), right, __eval));

    }

  }

  static public class Break extends org.rascalmpl.ast.Statement.Break {

    public Break(IConstructor __param1, Target __param2) {
      super(__param1, __param2);
    }

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);
     
      if (getTarget().isEmpty()) {
        throw new BreakException();
      }
      else {
        throw new BreakException(Names.name(getTarget().getName()));
      }
     
    }

  }

  static public class Continue extends org.rascalmpl.ast.Statement.Continue {

    public Continue(IConstructor __param1, Target __param2) {
      super(__param1, __param2);
    }

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);

      if (getTarget().isEmpty()) {
        throw new ContinueException();
      }
      else {
        throw new ContinueException(Names.name(getTarget().getName()));
      }

    }

  }

  static public class DoWhile extends org.rascalmpl.ast.Statement.DoWhile {

    public DoWhile(IConstructor __param1, Label __param2,
        org.rascalmpl.ast.Statement __param3,
        org.rascalmpl.ast.Expression __param4) {
      super(__param1, __param2, __param3, __param4);
    }

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);
     
      org.rascalmpl.ast.Statement body = this.getBody();
      org.rascalmpl.ast.Expression generator = this.getCondition();
      IBooleanResult gen;
      Environment old = __eval.getCurrentEnvt();
      String label = null;
      if (!this.getLabel().isEmpty()) {
        label = org.rascalmpl.interpreter.utils.Names.name(this
            .getLabel().getName());
      }
      __eval.__getAccumulators().push(
          new Accumulator(__eval.__getVf(), label));
      IValue value = null;
      try {
        while (true) {
          try {
            try {
              body.interpret(__eval);
            }
            catch (BreakException e) {
              value = __eval.__getAccumulators().pop().done();
              return org.rascalmpl.interpreter.result.ResultFactory
                  .makeResult(value.getType(), value, __eval);
            }
            catch (ContinueException e) {
              // just continue;
            }
 
            gen = generator.getBacktracker(__eval);
            gen.init();
            if (__eval.isInterrupted()) {
              throw new InterruptException(__eval.getStackTrace(), __eval.getCurrentAST().getLocation());
            }
            if (!(gen.hasNext() && gen.next())) {
              value = __eval.__getAccumulators().pop().done();
              return org.rascalmpl.interpreter.result.ResultFactory
                  .makeResult(value.getType(), value, __eval);
            }
          } finally {
            __eval.unwind(old);
          }
        }
      }
      finally {
        if (value == null) {
          // make sure to pop the accumulators even in the case of exceptions
          __eval.__getAccumulators().pop().done();
        }
      }
    }

  }

  static public class EmptyStatement extends
      org.rascalmpl.ast.Statement.EmptyStatement {

    public EmptyStatement(IConstructor __param1) {
      super(__param1);
    }

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);

      return org.rascalmpl.interpreter.result.ResultFactory.nothing();

    }

  }

  static public class Expression extends
      org.rascalmpl.ast.Statement.Expression {

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

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);
     
      Environment old = __eval.getCurrentEnvt();

      try {
        __eval.pushEnv();
        return this.getExpression().interpret(__eval);
      } finally {
        __eval.unwind(old);
      }

    }

  }

  static public class Fail extends org.rascalmpl.ast.Statement.Fail {

    public Fail(IConstructor __param1, Target __param2) {
      super(__param1, __param2);
    }

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);
     
      if (!this.getTarget().isEmpty()) {
        throw new Failure(Names.name(this.getTarget().getName()));
      }

      throw new Failure();

    }

  }

  static public class Filter extends org.rascalmpl.ast.Statement.Filter {

    public Filter(IConstructor __param1) {
      super(__param1);
    }
   
    public Result<IValue> interpret(IEvaluator<Result<IValue>> __eval) {

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);

      throw new Filtered();
   
    }

  }

  static public class For extends org.rascalmpl.ast.Statement.For {

    public For(IConstructor __param1, Label __param2,
        List<org.rascalmpl.ast.Expression> __param3,
        org.rascalmpl.ast.Statement __param4) {
      super(__param1, __param2, __param3, __param4);
    }

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);
     
      org.rascalmpl.ast.Statement body = this.getBody();
      List<org.rascalmpl.ast.Expression> generators = this
          .getGenerators();
      int size = generators.size();
      IBooleanResult[] gens = new IBooleanResult[size];
      Environment old = __eval.getCurrentEnvt();
      Environment[] olds = new Environment[size];

      Result<IValue> result = org.rascalmpl.interpreter.result.ResultFactory
          .makeResult(org.rascalmpl.interpreter.Evaluator.__getTf()
              .voidType(), __eval.__getVf().list(), __eval);

      String label = null;
      if (!this.getLabel().isEmpty()) {
        label = org.rascalmpl.interpreter.utils.Names.name(this
            .getLabel().getName());
      }
      __eval.__getAccumulators().push(
          new Accumulator(__eval.__getVf(), label));

      // TODO: does this prohibit that the body influences the behavior
      // of the generators??

      int i = 0;
      boolean normalCflow = false;
      try {
        olds[0] = __eval.getCurrentEnvt();
        __eval.pushEnv();
        gens[0] = generators.get(0).getBacktracker(__eval);
        gens[0].init();

        while (i >= 0 && i < size) {
          if (__eval.isInterrupted()) {
            throw new InterruptException(__eval.getStackTrace(), __eval.getCurrentAST().getLocation());
          }
          if (gens[i].hasNext() && gens[i].next()) {
            if (i == size - 1) {
              // NB: no result handling here.
              __eval.setCurrentAST(body);
             
              try {
                body.interpret(__eval);
              }
              catch (Failure e) {
                // TODO: failure should undo variable assignments outside the scope of the for!
                if (!e.hasLabel()) {
                  continue;
                }
                else if (!getLabel().isEmpty() && e.getLabel().equals(Names.name(getLabel().getName()))) {
                  continue;
                }

                throw e;
              }
              catch (ContinueException e) {
                if (!e.hasLabel() && getLabel().isEmpty()) {
                  continue;
                }
                else if (!getLabel().isEmpty() && e.getLabel().equals(Names.name(getLabel().getName()))) {
                  continue;
                }

                throw e;
              }
              catch (BreakException e) {
                if (!e.hasLabel() && getLabel().isEmpty()) {
                  break;
                 
                }
                else if (!getLabel().isEmpty() && e.getLabel().equals(Names.name(getLabel().getName()))) {
                  break;
                }

                throw e;
              }
            } else {
              i++;
              olds[i] = __eval.getCurrentEnvt();
              __eval.pushEnv();
              gens[i] = generators.get(i).getBacktracker(__eval);
              gens[i].init();
            }
          } else {
            __eval.unwind(olds[i]);
            i--;
          }
        }
        // TODO: this is not enough, we must also detect
        // break and return a list result then.
        normalCflow = true;
      } finally {
        IValue value = __eval.__getAccumulators().pop().done();
        if (normalCflow) {
          result = org.rascalmpl.interpreter.result.ResultFactory
              .makeResult(value.getType(), value, __eval);
        }
        __eval.unwind(old);
      }
      return result;

    }

  }

  static public class FunctionDeclaration extends
      org.rascalmpl.ast.Statement.FunctionDeclaration {

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

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);
     
      return this.getFunctionDeclaration().interpret(__eval);

    }

  }

  static public class GlobalDirective extends
      org.rascalmpl.ast.Statement.GlobalDirective {

    public GlobalDirective(IConstructor __param1, Type __param2,
        List<QualifiedName> __param3) {
      super(__param1, __param2, __param3);
    }

    @Override
    public Result<IValue> interpret(IEvaluator<Result<IValue>> __eval) {
      throw new NotYetImplemented(this); // TODO
    }

  }

  static public class IfThen extends org.rascalmpl.ast.Statement.IfThen {

    public IfThen(IConstructor __param1, Label __param2,
        List<org.rascalmpl.ast.Expression> __param3,
        org.rascalmpl.ast.Statement __param4) {
      super(__param1, __param2, __param3, __param4);
    }

    @Override
    public Result<IValue> interpret(IEvaluator<Result<IValue>> __eval) {
     
      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);
     
      org.rascalmpl.ast.Statement body = this.getThenStatement();
      List<org.rascalmpl.ast.Expression> generators = this
          .getConditions();
      int size = generators.size();
      IBooleanResult[] gens = new IBooleanResult[size];
      Environment[] olds = new Environment[size];
      Environment old = __eval.getCurrentEnvt();
     
      int i = 0;
      try {
        olds[0] = __eval.getCurrentEnvt();
        __eval.pushEnv();
        gens[0] = generators.get(0).getBacktracker(__eval);
        gens[0].init();

        while (i >= 0 && i < size) {

          if (__eval.isInterrupted()) {
            throw new InterruptException(__eval.getStackTrace(), __eval.getCurrentAST().getLocation());
          }
          if (gens[i].hasNext() && gens[i].next()) {
            if (i == size - 1) {
              __eval.setCurrentAST(body);
              try {
                return body.interpret(__eval);
              }
              catch (Failure e) {
                if (!e.hasLabel()) {
                  continue;
                }
                else if (!getLabel().isEmpty() && e.getLabel().equals(Names.name(getLabel().getName()))) {
                  continue;
                }

                throw e;
              }
            }
            else {
              i++;
              gens[i] = generators.get(i).getBacktracker(__eval);
              gens[i].init();
              olds[i] = __eval.getCurrentEnvt();
              __eval.pushEnv();
            }
          } else {
            __eval.unwind(olds[i]);
            __eval.pushEnv();
            i--;
          }
        }
      } finally {
        __eval.unwind(old);
      }
      return org.rascalmpl.interpreter.result.ResultFactory.nothing();

    }

  }

  static public class IfThenElse extends
      org.rascalmpl.ast.Statement.IfThenElse {

    public IfThenElse(IConstructor __param1, Label __param2,
        List<org.rascalmpl.ast.Expression> __param3,
        org.rascalmpl.ast.Statement __param4,
        org.rascalmpl.ast.Statement __param5) {
      super(__param1, __param2, __param3, __param4, __param5);
    }

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);
     
      org.rascalmpl.ast.Statement body = this.getThenStatement();
      List<org.rascalmpl.ast.Expression> generators = this
          .getConditions();
      int size = generators.size();
      IBooleanResult[] gens = new IBooleanResult[size];
      Environment[] olds = new Environment[size];
      Environment old = __eval.getCurrentEnvt();

      int i = 0;
      try {
        olds[0] = __eval.getCurrentEnvt();
        __eval.pushEnv();
        gens[0] = generators.get(0).getBacktracker(__eval);
        gens[0].init();

        while (i >= 0 && i < size) {

          if (__eval.isInterrupted()) {
            throw new InterruptException(__eval.getStackTrace(), __eval.getCurrentAST().getLocation());
          }
          if (gens[i].hasNext() && gens[i].next()) {
            if (i == size - 1) {
              __eval.setCurrentAST(body);
              try {
                return body.interpret(__eval);
              }
              catch (Failure e) {
                if (!e.hasLabel()) {
                  continue;
                }
                else if (!getLabel().isEmpty() && e.getLabel().equals(Names.name(getLabel().getName()))) {
                  continue;
                }

                throw e;
              }
            }
            else {
              i++;
              gens[i] = generators.get(i).getBacktracker(__eval);
              gens[i].init();
              olds[i] = __eval.getCurrentEnvt();
              __eval.pushEnv();
            }
          } else {
            __eval.unwind(olds[i]);
            __eval.pushEnv();
            i--;
          }
        }
      } finally {
        __eval.unwind(old);
      }

      org.rascalmpl.ast.Statement elsePart = this.getElseStatement();
      __eval.setCurrentAST(elsePart);
      return elsePart.interpret(__eval);

    }

  }

  static public class Insert extends org.rascalmpl.ast.Statement.Insert {

    public Insert(IConstructor __param1, DataTarget __param2,
        org.rascalmpl.ast.Statement __param3) {
      super(__param1, __param2, __param3);
    }

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);
     
      throw new org.rascalmpl.interpreter.control_exceptions.Insert(this
          .getStatement().interpret(__eval));

    }

  }

  static public class NonEmptyBlock extends
      org.rascalmpl.ast.Statement.NonEmptyBlock {

    public NonEmptyBlock(IConstructor __param1, Label __param2,
        List<org.rascalmpl.ast.Statement> __param3) {
      super(__param1, __param2, __param3);
    }

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);
     
      Result<IValue> r = org.rascalmpl.interpreter.result.ResultFactory
          .nothing();
      Environment old = __eval.getCurrentEnvt();

      __eval.pushEnv(this);
      try {
        for (org.rascalmpl.ast.Statement stat : this.getStatements()) {
          __eval.setCurrentAST(stat);
          r = stat.interpret(__eval);
        }
      } finally {
        __eval.unwind(old);
      }
      return r;

    }

  }

  static public class Return extends org.rascalmpl.ast.Statement.Return {

    public Return(IConstructor __param1, org.rascalmpl.ast.Statement __param2) {
      super(__param1, __param2);
    }

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);
     
      throw new org.rascalmpl.interpreter.control_exceptions.Return(this
          .getStatement().interpret(__eval), this.getStatement()
          .getLocation());

    }

  }

  static public class Solve extends org.rascalmpl.ast.Statement.Solve {

    public Solve(IConstructor __param1, List<QualifiedName> __param2,
        Bound __param3, org.rascalmpl.ast.Statement __param4) {
      super(__param1, __param2, __param3, __param4);
    }

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);
     
      int size = this.getVariables().size();
      QualifiedName vars[] = new QualifiedName[size];
      IValue currentValue[] = new IValue[size];

      Environment old = __eval.getCurrentEnvt();

      try {
        List<QualifiedName> varList = this.getVariables();

        for (int i = 0; i < size; i++) {
          QualifiedName var = varList.get(i);
          vars[i] = var;
          Result<IValue> tmp = __eval.getCurrentEnvt().getSimpleVariable(var);
         
          if (tmp == null) {
            throw new UndeclaredVariable(Names.fullName(var), var);
          }
          if (tmp.getValue() == null) {
            throw new UninitializedVariable(Names.fullName(var),
                var);
          }
          currentValue[i] = tmp.getValue();
        }

        __eval.pushEnv();
        org.rascalmpl.ast.Statement body = this.getBody();

        int max = -1;

        Bound bound = this.getBound();
        if (bound.isDefault()) {
          Result<IValue> res = bound.getExpression()
              .interpret(__eval);
          if (!res.getType().isInteger()) {
            throw new UnexpectedType(
                org.rascalmpl.interpreter.Evaluator.__getTf()
                    .integerType(), res.getType(), this);
          }
          max = ((IInteger) res.getValue()).intValue();
          if (max <= 0) {
            throw org.rascalmpl.interpreter.utils.RuntimeExceptionFactory
                .indexOutOfBounds((IInteger) res.getValue(),
                    __eval.getCurrentAST(), __eval
                        .getStackTrace());
          }
        }

        Result<IValue> bodyResult = null;

        boolean change = true;
        int iterations = 0;

        while (change && (max == -1 || iterations < max)) {
          change = false;
          iterations++;
          if (__eval.isInterrupted()) {
            throw new InterruptException(__eval.getStackTrace(), __eval.getCurrentAST().getLocation());
          }
          bodyResult = body.interpret(__eval);
          for (int i = 0; i < size; i++) {
            QualifiedName var = vars[i];
            Result<IValue> v = __eval.getCurrentEnvt().getVariable(
                var);
            if (currentValue[i] == null
                || !v.getValue().isEqual(currentValue[i])) {
              change = true;
              currentValue[i] = v.getValue();
            }
          }
        }
        return bodyResult;
      } finally {
        __eval.unwind(old);
      }

    }

  }

  static public class Switch extends org.rascalmpl.ast.Statement.Switch {
    private List<CaseBlock> blocks;

    public Switch(IConstructor __param1, Label __param2,
        org.rascalmpl.ast.Expression __param3, List<Case> cases) {
      super(__param1, __param2, __param3, cases);
      blocks = Cases.precompute(cases);
    }

    @Override
    public Result<IValue> interpret(IEvaluator<Result<IValue>> __eval) {
     
      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);
     
      Result<IValue> subject = this.getExpression().interpret(__eval);

      for (CaseBlock cs : blocks) {
        if (cs.matchAndEval(__eval, subject)) {
          return org.rascalmpl.interpreter.result.ResultFactory
              .nothing();
        }
      }

      return ResultFactory.nothing();
    }
  }

  static public class Throw extends org.rascalmpl.ast.Statement.Throw {

    public Throw(IConstructor __param1, org.rascalmpl.ast.Statement __param2) {
      super(__param1, __param2);
    }

    @Override
    public Result<IValue> interpret(IEvaluator<Result<IValue>> __eval) {
      throw new org.rascalmpl.interpreter.control_exceptions.Throw(this
          .getStatement().interpret(__eval).getValue(), __eval
          .getCurrentAST(), __eval.getStackTrace());
    }

  }

  static public class Try extends org.rascalmpl.ast.Statement.Try {

    public Try(IConstructor __param1, org.rascalmpl.ast.Statement __param2,
        List<Catch> __param3) {
      super(__param1, __param2, __param3);
    }

    @Override
    public Result<IValue> interpret(IEvaluator<Result<IValue>> __eval) {
      return evalStatementTry(__eval, this.getBody(), this.getHandlers(), null);
    }
   
    static public Result<IValue> evalStatementTry(IEvaluator<Result<IValue>> eval, org.rascalmpl.ast.Statement body, java.util.List<Catch> handlers, org.rascalmpl.ast.Statement finallyBody) {
      Result<IValue> res = org.rascalmpl.interpreter.result.ResultFactory.nothing();

      try {
        res = body.interpret(eval);
      } catch (org.rascalmpl.interpreter.control_exceptions.Throw e) {
        IValue eValue = e.getException();

        boolean handled = false;

        for (Catch c : handlers) {
          if (c.isDefault()) {
            res = c.getBody().interpret(eval);
            handled = true;
            break;
          }
          if (Cases.matchAndEval(makeResult(eValue.getType(), eValue, eval), c.getPattern(), c.getBody(), eval)) {
            handled = true;
            break;
          }
        }

        if (!handled)
          throw e;
      } finally {
        if (finallyBody != null) {
          finallyBody.interpret(eval);
        }
      }
      return res;
    }
  }

  static public class TryFinally extends
      org.rascalmpl.ast.Statement.TryFinally {

    public TryFinally(IConstructor __param1, org.rascalmpl.ast.Statement __param2,
        List<org.rascalmpl.ast.Catch> __param3, org.rascalmpl.ast.Statement __param4) {
      super(__param1, __param2, __param3, __param4);
    }

    @Override
    public Result<IValue> interpret(IEvaluator<Result<IValue>> __eval) {
     
      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);

      return org.rascalmpl.semantics.dynamic.Statement.Try.evalStatementTry(__eval, this.getBody(), this.getHandlers(),
          this.getFinallyBody());
   
    }
  }

  static public class VariableDeclaration extends
      org.rascalmpl.ast.Statement.VariableDeclaration {

    public VariableDeclaration(IConstructor __param1,
        LocalVariableDeclaration __param2) {
      super(__param1, __param2);
    }

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);

      return this.getDeclaration().interpret(__eval);

    }

  }

  static public class Visit extends org.rascalmpl.ast.Statement.Visit {

    public Visit(IConstructor __param1, Label __param2,
        org.rascalmpl.ast.Visit __param3) {
      super(__param1, __param2, __param3);
    }

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

      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);
     
      return this.getVisit().interpret(__eval);

    }

  }

  static public class While extends org.rascalmpl.ast.Statement.While {

    public While(IConstructor __param1, Label __param2,
        List<org.rascalmpl.ast.Expression> __param3,
        org.rascalmpl.ast.Statement __param4) {
      super(__param1, __param2, __param3, __param4);
    }

    @Override
    public Result<IValue> interpret(IEvaluator<Result<IValue>> __eval) {
      IValue value = null;
     
      __eval.setCurrentAST(this);
      __eval.notifyAboutSuspension(this);

      org.rascalmpl.ast.Statement body = this.getBody();
      List<org.rascalmpl.ast.Expression> generators = this
          .getConditions();

      int size = generators.size();
      IBooleanResult[] gens = new IBooleanResult[size];
      Environment[] olds = new Environment[size];
      Environment old = __eval.getCurrentEnvt();

      String label = null;
      if (!this.getLabel().isEmpty()) {
        label = org.rascalmpl.interpreter.utils.Names.name(this
            .getLabel().getName());
      }
      __eval.__getAccumulators().push(
          new Accumulator(__eval.__getVf(), label));
      try {
        // a while statement is different from a for statement, the body of
        // the while can influence the
        // variables that are used to test the condition of the loop
        // while does not iterate over all possible matches, rather it
        // produces every time the first match
        // that makes the condition true
        loop: while (true) {
          int i = 0;
          try {
            if (__eval.isInterrupted()) {
              throw new InterruptException(__eval.getStackTrace(), __eval.getCurrentAST().getLocation());
            }
           
            olds[0] = __eval.getCurrentEnvt();
            gens[0] = generators.get(0).getBacktracker(__eval);
            gens[0].init();
 
            conditions:while (i >= 0 && i < size) {
              __eval.unwind(olds[i]);
              __eval.pushEnv();
 
              if (__eval.isInterrupted()) {
                throw new InterruptException(__eval.getStackTrace(), __eval.getCurrentAST().getLocation());
              }
              if (gens[i].hasNext() && gens[i].next()) {
                if (i == size - 1) {
                  __eval.setCurrentAST(body);
                 
                  try {
                    body.interpret(__eval);
                    continue loop;
                  }
                  catch (Failure e) {
                    // try next assignment of generators!
                    // TODO: failure should undo assignment
                    if (!e.hasLabel() && getLabel().isEmpty()) {
                      continue conditions;
                    }
                    else if (!getLabel().isEmpty() && e.getLabel().equals(Names.name(getLabel().getName()))) {
                      continue conditions;
                    }
 
                    throw e;
                  }
                  catch (ContinueException e) {
                    // try next assignment of generators!
                    if (!e.hasLabel() && getLabel().isEmpty()) {
                      continue loop;
                    }
                    else if (!getLabel().isEmpty() && e.getLabel().equals(Names.name(getLabel().getName()))) {
                      continue loop;
                    }
 
                    throw e;
                  }
                  catch (BreakException e) {
                    if (!e.hasLabel() && getLabel().isEmpty()) {
                      value = __eval.__getAccumulators().pop().done();
                      return org.rascalmpl.interpreter.result.ResultFactory
                          .makeResult(value.getType(), value, __eval);
                    }
                    else if (!getLabel().isEmpty() && e.getLabel().equals(Names.name(getLabel().getName()))) {
                      value = __eval.__getAccumulators().pop().done();
                      return org.rascalmpl.interpreter.result.ResultFactory
                          .makeResult(value.getType(), value, __eval);
                    }
 
                    throw e;
                  }
                }
                else {
                  i++;
                  gens[i] = generators
                      .get(i).getBacktracker(__eval);
                  gens[i].init();
                  olds[i] = __eval.getCurrentEnvt();
                }
              } else {
                i--;
              }
            }
          } finally {
            __eval.unwind(old);
          }
          value = __eval.__getAccumulators().pop().done();
          return org.rascalmpl.interpreter.result.ResultFactory
              .makeResult(value.getType(), value, __eval);
        }
      }
      finally   {
        if (value == null) {
          // make sure to always pop the accumulator when it hasn't been popped yet
          __eval.__getAccumulators().pop().done();
        }
      }

    }

  }

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

Related Classes of org.rascalmpl.semantics.dynamic.Statement$Throw

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.