/* Author: Jeff Dalton <J.Dalton@ed.ac.uk>
 * Updated: Wed Dec  5 00:30:36 2001 by Jeff Dalton
 * Copyright: (c) 2001, AIAI, University of Edinburgh
 */

package ix.icore.process;

import java.util.*;

import ix.icore.domain.Schema;
import ix.util.*;
import ix.util.lisp.*;

public class Variable implements Comparable {

    Object name;		// must be Comparable
    Object value;

    // Info and debugging fields
    static List allVariables = new LListCollector();
    static int count = 0;
    public int number = ++count;
    public PNode sourceNode;
    public Schema sourceSchema;

    public Variable(Object name) {
	this.name = name;
	allVariables.add(this);
    }

    public Object getName() { return name; }

    public Object getValue() { return value; }

    public void setValue (Object v) {
	Debug.noteln("Setting value of " + this + " to " + v);
	this.value = v;
    }

    public int compareTo(Object o) {
	if (o instanceof Variable)
	    return ((Comparable)name).compareTo(((Variable)o).name);
	else
	    throw new ClassCastException
		("Cannot compare Variable " + this + " to " + o);
    }

    public String displayString() {
	return "[" + number + ":" + name
	    + (value == null ? "" : "=" + value)
	    + "]";
    }

    public String toString() {
	return displayString();
    }

    /* Static utilities */

    public static Set varsIn(LList tree) {
	final Set vars = new HashSet();
	tree.walkTree(new Function1() {
	    public Object funcall(Object item) {
		if (item instanceof Variable)
		    vars.add(item);
		return null;
	    }
	});
	return vars;
    }

    public static Set unboundVarsIn(Collection c) {
	Set vars = new HashSet();
	for (Iterator i = c.iterator(); i.hasNext();) {
	    Variable v = (Variable)i.next();
	    if (v.getValue() == null)
		vars.add(v);
	}
	return vars;
    }

    public static Object removeVars(Object tree) {
	if (tree instanceof Variable)
	    return ((Variable)tree).getName();
	else if (tree instanceof Cons) {
	    Cons t = (Cons)tree;
	    return new Cons(removeVars(t.car()), (LList)removeVars(t.cdr()));
	}
	else
	    return tree;
    }

}
