package playingWithLists;

public class MySchemeList<Any> implements SchemeList<Any> 
{
	
    private Any carValue;
    private MySchemeList<Any> cdrValue;
    private boolean isNil;

    public MySchemeList() {
    	isNil = true;
    }
      
    private MySchemeList(Any i, MySchemeList<Any> rest) {
    	isNil = false;
    	carValue = i;
    	cdrValue = rest;
    }
     
    public MySchemeList<Any> cons(Any x) {
    	return new MySchemeList<Any>(x,this);
    }
    
    public Any car() {
    	if (isNil())
    		throw new java.util.NoSuchElementException();
    	else
    		return carValue;
    }
    
    public MySchemeList<Any> cdr() {
       	if (isNil())
    		throw new java.util.NoSuchElementException();
       	else
       		return cdrValue;
    }
    
    public boolean isNil() {
    	return isNil;
    }
	
    public void setCar(Any x) {
       	if (isNil())
    		throw new java.util.NoSuchElementException();
       	else
       		carValue = x;
    }
    
    public void setCdr(MySchemeList<Any> x) {
       	if (isNil())
    		throw new java.util.NoSuchElementException();
       	else 
       		cdrValue = x;
    }
    
    public void setNil() {
    	isNil = true;
    }
    
    public void setNotNil() {
    	isNil = false;
    }
    
    public String toString() {
    	return toStringUptoDepth(100);
    }
    
    private String toStringUptoDepth(int d) {
    	if (d==0) return "...";
    	else
    		if (isNil) {
    			return "[]";
    		} else {
    			return 
    			"[" + 
    			carValue + 
    			"," + 
    			cdrValue.toStringUptoDepth(d-1) + 
    			"]";
    		} 	
    }
    
    // for convenience, the following constructor
    // makes a list from an array
    
    public MySchemeList(Any [] elements) {
    	if (elements.length == 0) {
    	   isNil = true;
    	} else {
    		isNil = false;
    		MySchemeList<Any> rest = new MySchemeList<Any>();
    		for (int i= elements.length - 1; i >= 1; i--) {
    			rest = new MySchemeList<Any>(elements[i],rest);
    		}
    		carValue = elements[0];
    		cdrValue = rest;
       }
    }
}
