// Path: src/java/minijava/ast/Call.java
// public class Call extends Expression {
// 
// 	public final Expression receiver;
// 	public final String name;
// 	public final NodeList<Expression> rands;
// 
// 	public Call(Expression receiver, String name, NodeList<Expression> rands) {
// 		super();
// 		this.receiver = receiver;
// 		this.name = name;
// 		this.rands = rands;
// 	}
// 
// 	@Override
// 	public <R> R accept(Visitor<R> v) {
// 		return v.visit(this);
// 	}
// 
// }
// 
// Path: src/java/minijava/ast/Expression.java
// public abstract class Expression extends AST {
// 	
// 	/**
// 	 * The type of an expression is set by the type checking phase.
// 	 */
// 	public Type type;
// 
// 	public Type getType() {
// 		Assert.assertNotNull("Was this AST typechecked?", type);
// 		return type;
// 	}
// 	
// 	public void setType(Type theType) {
// 		//Assert.assertNull(type); 
// 		//As our visitor is written, we expect the types of some nodes to be set multiple times.
// 		//as long as there is no conflict in these type settings, there is no problem, and the assertion has been
// 		//modified to reflect that.
// 		assert(type==null || type.equals(theType));		
// 		type = theType;
// 	}
// 
// }
// 
// Path: src/java/minijava/ast/ObjectType.java
// public class ObjectType extends Type {
// 	
// 	public final String name;
// 
// 	public ObjectType(String name) {
// 		super();
// 		this.name = name;
// 	}
// 
// 	@Override
// 	public <R> R accept(Visitor<R> v) {
// 		return v.visit(this);
// 	}
// 
// 	@Override
// 	public boolean equals(Object other) {
// 		if (this.getClass()==other.getClass()) {
// 			return this.name.equals(((ObjectType)other).name);
// 		}
// 		return false;
// 	}
// }
// 
// Path: src/java/minijava/ast/Type.java
// public abstract class Type extends AST {
// 	
// 	@Override
// 	public abstract boolean equals(Object other);
// 
// }


import minijava.ast.Call;
import minijava.ast.Expression;
import minijava.ast.ObjectType;
import minijava.ast.Type;
package minijava.typechecker;


/**
 * A centralised interface to record errors. 
 * 
 * @author kdvolder
 */
public class ErrorReport {
	
	private ErrorMessage firstError = null;
	
	public ErrorReport() {}

	/**
	 * Add an error to the ErrorReport.
	 * <p>
	 * In this implementation the msg is simply printed to System.out. Also, the first message
	 * is saved, so it can be verified by unit tests.
	 */
	void report(ErrorMessage msg) {
		if (firstError==null) 
			firstError = msg;
		System.out.println(msg);
	}
	
	/**
	 * To allow processing all of the input (so that as many errors as possible can be
	 * reported) and raising an error only in the end
	 * this method is provided. You should call this method when you are done reporting
	 * errors.
	 * <p>
	 * This method will raise an Exception if the error report contains some errors, 
	 * otherwise the method will return normally.
	 * <p>
	 * @throws TypeCheckerException 
	 */
	public void close() throws TypeCheckerException {
		if (firstError!=null)
			throw new TypeCheckerException(firstError);
	}

	public void duplicateDefinition(String name) {
		report(ErrorMessage.duplicateDefinition(name));
	}

	public void undefinedId(String name) {
		report(ErrorMessage.undefinedId(name));
	}
	
// Path: src/java/minijava/ast/Call.java
// public class Call extends Expression {
// 
// 	public final Expression receiver;
// 	public final String name;
// 	public final NodeList<Expression> rands;
// 
// 	public Call(Expression receiver, String name, NodeList<Expression> rands) {
// 		super();
// 		this.receiver = receiver;
// 		this.name = name;
// 		this.rands = rands;
// 	}
// 
// 	@Override
// 	public <R> R accept(Visitor<R> v) {
// 		return v.visit(this);
// 	}
// 
// }
// 
// Path: src/java/minijava/ast/Expression.java
// public abstract class Expression extends AST {
// 	
// 	/**
// 	 * The type of an expression is set by the type checking phase.
// 	 */
// 	public Type type;
// 
// 	public Type getType() {
// 		Assert.assertNotNull("Was this AST typechecked?", type);
// 		return type;
// 	}
// 	
// 	public void setType(Type theType) {
// 		//Assert.assertNull(type); 
// 		//As our visitor is written, we expect the types of some nodes to be set multiple times.
// 		//as long as there is no conflict in these type settings, there is no problem, and the assertion has been
// 		//modified to reflect that.
// 		assert(type==null || type.equals(theType));		
// 		type = theType;
// 	}
// 
// }
// 
// Path: src/java/minijava/ast/ObjectType.java
// public class ObjectType extends Type {
// 	
// 	public final String name;
// 
// 	public ObjectType(String name) {
// 		super();
// 		this.name = name;
// 	}
// 
// 	@Override
// 	public <R> R accept(Visitor<R> v) {
// 		return v.visit(this);
// 	}
// 
// 	@Override
// 	public boolean equals(Object other) {
// 		if (this.getClass()==other.getClass()) {
// 			return this.name.equals(((ObjectType)other).name);
// 		}
// 		return false;
// 	}
// }
// 
// Path: src/java/minijava/ast/Type.java
// public abstract class Type extends AST {
// 	
// 	@Override
// 	public abstract boolean equals(Object other);
// 
// }


// Path: src/java/minijava/typechecker/ErrorReport.java
import minijava.ast.Call;
import minijava.ast.Expression;
import minijava.ast.ObjectType;
import minijava.ast.Type;

package minijava.typechecker;


/**
 * A centralised interface to record errors. 
 * 
 * @author kdvolder
 */
public class ErrorReport {
	
	private ErrorMessage firstError = null;
	
	public ErrorReport() {}

	/**
	 * Add an error to the ErrorReport.
	 * <p>
	 * In this implementation the msg is simply printed to System.out. Also, the first message
	 * is saved, so it can be verified by unit tests.
	 */
	void report(ErrorMessage msg) {
		if (firstError==null) 
			firstError = msg;
		System.out.println(msg);
	}
	
	/**
	 * To allow processing all of the input (so that as many errors as possible can be
	 * reported) and raising an error only in the end
	 * this method is provided. You should call this method when you are done reporting
	 * errors.
	 * <p>
	 * This method will raise an Exception if the error report contains some errors, 
	 * otherwise the method will return normally.
	 * <p>
	 * @throws TypeCheckerException 
	 */
	public void close() throws TypeCheckerException {
		if (firstError!=null)
			throw new TypeCheckerException(firstError);
	}

	public void duplicateDefinition(String name) {
		report(ErrorMessage.duplicateDefinition(name));
	}

	public void undefinedId(String name) {
		report(ErrorMessage.undefinedId(name));
	}
	
	public void typeError(Expression exp, Type expected, Type actual) {