/* * This file is part of the OpenJML project. * Author: David R. Cok */ package org.jmlspecs.openjml.esc; import java.io.StringWriter; import java.io.Writer; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.jmlspecs.annotation.NonNull; import org.jmlspecs.annotation.Pure; import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.tree.JCTree.JCIdent; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.util.Context; /** * A BasicProgram is an equivalent representation of a method: * <UL> * <LI>it expresses the program as a DAG of basic blocks * <LI>each block represents a non-branching set of code * </UL> * The BasicBlocks are allowed to contain regular Java/JML statements but derived * classes may make additional transformation and have restrictions on the * kinds of statements allowed. This * class just holds the data and does not provide transforming functionality. * * @typeparam T the type of Block used by the program * @author David Cok */ // Note: everything declared protected is intended for use just in this class // and any future derived classes - not in the containing package abstract public class BasicProgramParent<T extends BasicProgramParent.BlockParent<T>> { /** Cached value of the symbol table */ @NonNull final public Symtab syms; /** Parent class constructor */ public BasicProgramParent(Context context) { //super(context); blocks = new ArrayList<T>(); syms = Symtab.instance(context); } /** Factory method to create a new block. */ abstract protected T newBlock(JCIdent id); /** A list of blocks that constitute this BasicProgram. */ //@ non_null protected List<T> blocks; /** A list of variables that will need to be declared at the beginning of * a basic block program. Boogie requires all declarations at the beginning * of the implementation. */ protected List<JCIdent> declarations = new ArrayList<JCIdent>(); /** Returns this program's list of blocks * @return this program's blocks */ @Pure @NonNull public List<T> blocks() { return blocks; } /** The method declaration generating this program */ protected JCMethodDecl methodDecl; /** Writes out the BasicProgram to the given Writer (e.g. log.noticeWriter) for diagnostics */ abstract public void write(Writer w); /** Writes the program to a String, returning it. */ @Override public String toString() { StringWriter sw = new StringWriter(); write(sw); return sw.toString(); } /** The base class for basic blocks; the type argument is derived Block class */ static abstract public class BlockParent<T extends BasicProgramParent.BlockParent<T>> { /** The identifier of the block */ /*@ non_null*/protected JCIdent id; /** Constructs a block with the given id. The id is used both for its * name, which is an identifier of the block, and its position, which * indicates the location or statement in the program that begins * the block. * * @param id */ public BlockParent(JCIdent id) { this.id = id; } /** Returns the id of the block * @return the block's id */ @Pure @NonNull public JCIdent id() { return id; } /** The ordered list of statements in the block */ @NonNull protected List<JCStatement> statements = new LinkedList<JCStatement>(); /** Returns the block's statements * @return the block's statements */ @Pure @NonNull public List<JCStatement> statements() { return statements; } /** The set of blocks that succeed this one */ @NonNull protected List<T> followers = new ArrayList<T>(); /** Returns the block's followers * @return the block's followers */ @Pure @NonNull public List<T> followers() { return followers; } /** The set of blocks that precede this one */ @NonNull protected List<T> preceders = new ArrayList<T>(); /** Returns the block's preceders * @return the block's preceders */ @Pure @NonNull public List<T> preceders() { return preceders; } /** Generates a human-readable String representation of the block */ @Override // @NonNull public String toString() { java.io.StringWriter s = new java.io.StringWriter(); write(s); return s.toString(); } /** Writes out the basic block to the given Writer * * @param w where to put a String representation of the block */ abstract public void write(Writer w); } }