Package org.jakstab.rtl.statements

Source Code of org.jakstab.rtl.statements.StatementSequence

/*
* StatementSequence.java - This file is part of the Jakstab project.
* Copyright 2007-2012 Johannes Kinder <jk@jakstab.org>
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, see <http://www.gnu.org/licenses/>.
*/

package org.jakstab.rtl.statements;

import java.io.Serializable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.jakstab.rtl.Context;
import org.jakstab.rtl.expressions.*;
import org.jakstab.ssl.CanonizationVisitor;
import org.jakstab.util.Logger;

/**
* A sequence of RTL statements, only used during SSL instantiation and in stub generation.
*
* @author Johannes Kinder
*/
public class StatementSequence implements Iterable<RTLStatement>, Serializable {

  @SuppressWarnings("unused")
  private final static Logger logger = Logger.getLogger(StatementSequence.class);
  private static final long serialVersionUID = -3750283603929931899L;


  private LinkedList<RTLStatement> sequence;

  /**
   * Creates a new empty statement sequence.
   */
  public StatementSequence() {
    sequence = new LinkedList<RTLStatement>();
  }

  /**
   * Inserts a statement before the start of this sequence when it is not null,
   * otherwise does nothing.
   *
   * @param statement the statement to be added.
   */
  public void addFirst(RTLStatement statement) {
    if (statement != null) {
      sequence.addFirst(statement);
    }
  }

  /**
   * Inserts a sequence of statements before the start of this sequence when the
   * sequence object is not null, otherwise does nothing.
   *
   * @param statements the statement sequence to be added
   */
  public void addFirst(StatementSequence statements) {
    if (statements != null) {
      sequence.addAll(0, statements.sequence);
    }
  }

  /**
   * Adds a statement to the end of this sequence when it is not null,
   * otherwise does nothing.
   *
   * @param statement the statement to be added.
   */
  public void addLast(RTLStatement statement) {
    if (statement != null) {
      sequence.addLast(statement);
    }
  }

  /**
   * Adds a sequence of statements to the end of this sequence when the sequence
   * object is not null, otherwise does nothing.
   *
   * @param statements the statement sequence to be added
   */
  public void addLast(StatementSequence statements) {
    if (statements != null) {
      sequence.addAll(statements.sequence);
    }
  }

  public Iterator<RTLStatement> iterator() {
    return sequence.iterator();
  }

  public void removeLast() {
    sequence.removeLast();
  }


  public RTLStatement getFirst() {
    return sequence.getFirst();
  }

  public RTLStatement getLast() {
    return sequence.getLast();
  }

  /**
   * Returns a canonical copy of this sequence. Canonization is required only
   * once, after parsing a SSL specification. Canonical statements do not contain
   * assignments of the special %RPT and %SKIP registers.
   *
   * NOTE: Unchanged elements are not copied but the originals are returned.
   *
   * @return this statement sequence converted to canonical form.
   */
  public StatementSequence canonize() {
    CanonizationVisitor visitor = new CanonizationVisitor();
   
    RTLExpression skipCondition = null;
    RTLExpression repeatCondition = null;
   
    LinkedList<RTLStatement> oldSequence = sequence;
    sequence = new LinkedList<RTLStatement>();

    /* Evaluate substatements */
    for (RTLStatement statement : oldSequence) {
      RTLStatement evaldStatement;
     
      if (statement instanceof AssignmentTemplate) {
        AssignmentTemplate a = (AssignmentTemplate)statement;
       
        RTLExpression genericEvaldLHS = a.getLeftHandSide().accept(visitor);
        RTLExpression evaldRHS = a.getRightHandSide().accept(visitor);

        if (!(genericEvaldLHS instanceof Writable))
          throw new RuntimeException("Error: LHS of assignment no longer writable after canonization: " +
              a.getLeftHandSide().toString() + " = " + genericEvaldLHS.toString());

        Writable evaldLHS = (Writable)genericEvaldLHS;

        /* Convert %SKIP assignments to conditionals */
        if (evaldLHS.equals(ExpressionFactory.SKIP)) {
          skipCondition = evaldRHS;
          continue;
        }

        /* Convert %RPT assignments to conditionals */
        if (evaldLHS.equals(ExpressionFactory.REPEAT)) {
          repeatCondition = evaldRHS;
          continue;
        }

        // if both sides are equal, remove this statement
        if (evaldLHS.equals(evaldRHS))
          continue;
       
        evaldStatement = new AssignmentTemplate(a.getBitWidth(), evaldLHS, evaldRHS);
       
      } else /* non AssignmentTemplate */ {
        evaldStatement = statement.evaluate(new Context());
      }

      addLast(evaldStatement);
    }
    if (sequence.size() < 1)
      return null;

    if (skipCondition != null) {
      RTLGoto skipGoto = new RTLGoto(ExpressionFactory.pc, skipCondition, RTLGoto.Type.STRING_LENGTH_CHECK);
      addFirst(skipGoto);
    }

    if (repeatCondition != null) {
      // Create a dummy goto statement, this will point to the instruction's address after instantiation
      if (!repeatCondition.equals(ExpressionFactory.FALSE)) {
        RTLStatement condGoto = new RTLGoto(null, repeatCondition, RTLGoto.Type.REPEAT);
        addLast(condGoto);
      }
    }

    return this;
  }
 
  /**
   * Move all bitrange expressions from the LHS of assignments to the RHS,
   * and convert all assignment templates to variable or memory assignments.
   * @return
   */
  public StatementSequence normalizeAssignments() {
    LinkedList<RTLStatement> oldSequence = sequence;
    sequence = new LinkedList<RTLStatement>();

    for (RTLStatement statement : oldSequence) {
      if (statement instanceof AssignmentTemplate)
        sequence.addLast(((AssignmentTemplate)statement).convertToSpecificAssignmentType());
      else
        sequence.addLast(statement);
     
    }
    return this;
  }


  public StatementSequence evaluate(Context context) {
    LinkedList<RTLStatement> oldSequence = sequence;
    sequence = new LinkedList<RTLStatement>();

    for (RTLStatement statement : oldSequence) {
      RTLStatement evaldStatement = statement.evaluate(context);
      if (evaldStatement != null) addLast(evaldStatement);
    }
    if (sequence.size() < 1)
      return null;

    return this;
  }

  public int getLength() {
    return sequence.size();
  }

  /**
   * @return the statement sequence
   */
  protected List<RTLStatement> getSequence() {
    return sequence;
  }

  public StatementSequence replace(RTLStatement statement, RTLStatement replacement) {
    LinkedList<RTLStatement> oldSequence = sequence;
    sequence = new LinkedList<RTLStatement>();
    for (RTLStatement stmt : oldSequence) {
      if (stmt.equals(statement)) {
        if (replacement != null) {
          addLast(replacement);
        }
      } else addLast(stmt);
    }
    if (sequence.size() < 1) {
      return null;
    }

    return this;
  }

  @Override
  public String toString() {
    StringBuilder res = new StringBuilder();
    res.append("{ ");
    for (RTLStatement statement : sequence) {
      res.append(statement.toString());
      res.append("; ");
    }
    res.append(" }");
    return res.toString();
  }

  public StatementSequence copy() {
    StatementSequence res = new StatementSequence();
    for (RTLStatement statement : sequence) {
      res.addLast(statement.copy());
    }
    return res;
  }

  public SetOfVariables getDefinedVariables() {
    SetOfVariables res = new SetOfVariables();
    for (RTLStatement s : sequence)
      res.addAll(s.getDefinedVariables());
    return res;
  }
 
}
TOP

Related Classes of org.jakstab.rtl.statements.StatementSequence

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.