package ic.ast;

/**
 * A class to keep track of how many scopes we have entered during printing. It
 * uses this information to indent each line appoporiately. To use:
 * <ul>
 * <li> In your pretty printer, make sure you never print "\n" in any method.  Use 
 * println instead.
 * 
 * <li> Change your class to extend the ScopeAwarePrinter class. This class 
 * defines print, println, and printf for you-
 * these methods will handle indentation automatically.
 * 
 * <li> To call those versions remove all occurences of "System.out." from your
 * code.
 * 
 * <li> Whenever you want to print a { and enter a scope, call enterScope().
 * Whenever you want to print a } and exit a scope, call exitScope().
 * </ul>
 */
public class ScopeAwarePrinter {
	
	/** The number of scopes the Vsitor is currently inside of */
	private int depth = 0;
	
	/** Was the last thing printed a new line? */
	private boolean startOfLine = true;

	/**
	 * Indicate that we have entered a Scope and should
	 * indent the contents of it more than we are currently
	 * indenting.  This takes care of printing a {.
	 */
	protected void enterScope() {
		depth++;
		println("{");
	}

	/**
	 * Indicate that we have exited a scope and need to
	 * change the indentation.  This takes care of printing a }.
	 */
	protected void exitScope() {
		depth--;
		println("}");
	}

	/**
	 * A variant of printf that is aware of line starts and 
	 * indentation.
	 */
	protected void printf(String s, Object... args) {
		if (startOfLine) pad();
		System.out.printf(s, args);
	}

	/**
	 * A variant of print that is aware of line starts and 
	 * indentation.
	 */
	protected void print(Object s) {
		if (startOfLine) pad();
		System.out.print(s);
	}
	
	
	/**
	 * A variant of println that is aware of line starts and 
	 * indentation.
	 */
	protected void println(Object s) {
		if (startOfLine) pad();
		print(s);
		println();
	}

	/**
	 * A variant of println that is aware of line starts and 
	 * indentation.
	 */
	protected void println() {
		System.out.println();
		startOfLine = true;
	}

	/**
	 * Insert spaces proportional to the current depth of
	 * scopes.  This is called in the above methods whenever
	 * we start printing after a new line.
	 */
	private void pad() {
		for (int i = 0; i < depth; i++) {
			System.out.print("  ");
		}
		startOfLine = false;
	}
}
