Package wyvern.targets.Common.wyvernIL.interpreter.core

Source Code of wyvern.targets.Common.wyvernIL.interpreter.core.Interpreter

package wyvern.targets.Common.wyvernIL.interpreter.core;

import wyvern.targets.Common.wyvernIL.IL.Stmt.Label;
import wyvern.targets.Common.wyvernIL.IL.Stmt.Statement;
import wyvern.targets.Common.wyvernIL.interpreter.values.BytecodeEmptyVal;
import wyvern.targets.Common.wyvernIL.interpreter.values.BytecodeTuple;
import wyvern.targets.Common.wyvernIL.interpreter.values.BytecodeValue;
import wyvern.targets.Common.wyvernIL.interpreter.visitors.BytecodeStatementVisitor;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* an intermediate level interpreter
* @author Tal Man
*
*/
public class Interpreter {

  private final BytecodeValue emptyVal;
  private BytecodeContext currentContext;
  private List<Statement> statements;
  private Map<Integer, Integer> labels; // Label id -> pc of next instruction
  private String finalName;
  private BytecodeValue finalValue;
  private boolean finalValuesSet;
  private int pc;

  /**
   * sets up the interpreter with a list of statements to execute and a
   * starting context
   * @param body
   *     a list of statements to be executed by the interpreter
   * @param context
   *     the starting context at the time of execution
   */
  public Interpreter(List<Statement> body, BytecodeContext context) {
    emptyVal = new BytecodeTuple(new ArrayList<BytecodeValue>());
    currentContext = context;
    statements = body;
    pc = 0;
    setUpLabels();
    finalValue = new BytecodeEmptyVal();
  }

  /**
   * sets up the interpreter with a list of statements to execute and an
   * empty starting context
   * @param s
   *     a list of statements to be executed by the interpreter
   */
  public Interpreter(List<Statement> s) {
    this(s, new BytecodeContextImpl());
  }

  /**
   * runs over all the statements and creates a dictionary of all the
   * labels created in them for future use
   */
  private void setUpLabels() {
    labels = new HashMap<Integer, Integer>();
    int labelLocation = 0;
    for (Statement statement : statements) {
      labelLocation++;
      if (statement instanceof Label) {
        Label label = (Label) statement;
        labels.put(label.getIdx(), labelLocation);
      }
    }
  }

  /**
   * runs the interpreter and returns the last value encountered
   * @return
   *     a BytecodeValue object representing the last value encountered
   */
  public BytecodeValue execute() {
      while (pc < statements.size()) {
        step();
      }
      return finalValue;
  }
 
  /**
   * executes a single step in the interpreter
   * @return
   *     the result of this single step
   */
  public BytecodeValue step() {
    finalValuesSet = false;
    Statement statement = statements.get(pc++);
    BytecodeStatementVisitor visitor;
    visitor = new BytecodeStatementVisitor(currentContext, this);
    currentContext = statement.accept(visitor);
    setFinalVals(emptyVal,"unit"); // if it wasn't set to something else
    return finalValue;
  }

  /*
   * for debugging purposes, prints the final result and the context
   */
  public void printContext() {
    System.out.println("\nFinal result:");
    System.out.println(finalName + ": " + finalValue);
    System.out.println("\nSimplified context:");
    System.out.println(currentContext.toSimpleString());
  }

  /**
   * sets the final values of the execution for this past statement, but
   * this method will only set the values once per instruction
   * @param val
   *     the final value to be set
   * @param name
   *     the name associated with that final value
   */
  public void setFinalVals(BytecodeValue val, String name) {
    if(!finalValuesSet) {
      finalValue = val;
      finalName = name;
      finalValuesSet = true;
    }
  }

  /**
   * returns the program counter for the instruction after a label
   * @param labelID
   *     the id of the label in question
   * @return
   *     the pc for the next instruction after it
   */
  public int getLabelPC(int labelID) {
    return labels.get(labelID);
  }

  /**
   * set the pc to a new value
   * @param newPc
   *     the new value of the pc
   */
  public void setProgramCounter(int newPc) {
    pc = newPc;
  }

  /**
   * gets the current pc
   * @return
   *     the current pc
   */
  public int getProgramCounter() {
    return pc;
  }
 
  /*
   *  causes the interpreter to finish executing, currently only used by
   *  the Return case of the statement visitor which is unused in the current
   *  IL implementation - so UNUSED
   */
  public void endExecution() {
    pc = statements.size() + 1;
  }
 
  /*
   * debug version of execute that prints information on a thrown exception
   * like which statement caused it and what is the context during that time
   */
  public BytecodeValue executeDebug() {
    try {
      while (pc < statements.size()) {
        step();
      }
      return finalValue;
    } catch(RuntimeException e) {
      System.err.println("\n >>>>>   ERROR   <<<<<<");
      System.err.println(e.getMessage());
      System.err.println("on statement:");
      System.err.println(statements.get(--pc));
      System.err.println("context:");
      System.err.println(currentContext);
      throw e;
    }
  }
 
  /*
   * gets the current working context (used only for tests)
   */
  public BytecodeContext getCurrentContext() {
    return currentContext;
  }
}
TOP

Related Classes of wyvern.targets.Common.wyvernIL.interpreter.core.Interpreter

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.