/* File: MatchEnv.java
 * Contains: A class for pattern-matching
 * Author: Jeff Dalton <J.Dalton@ed.ac.uk>
 * Created: January 1998
 * Updated: Tue Dec  4 23:25:42 2001 by Jeff Dalton
 * Copyright: (c) 1998, AIAI, University of Edinburgh
 */

package ix.util.match;

import java.util.*;

import ix.util.Debug;
import ix.util.Function1;

import ix.util.lisp.*;

/** 
 * A root class for objects that contain the bindings that result
 * from pattern-matching. <p>
 *
 * MatchEnvs are not used automatically in MatchTable-based matching;
 * they are merely available in case they are useful.  For instance, a
 * MatchCase tryMatch method might construct a MatchEnv while matching
 * and return it if the match succeeds.  It would then be passed to
 * the MatchCase's ifSelected method by the MatchTable.
 *
 * @see MatchTable
 * @see MatchCase
 */

public class MatchEnv extends Hashtable {

    public Object instantiateTree(Object tree) {
	if (tree instanceof ItemVar) {
	    Object neu = get(tree);
	    Debug.assert(neu != null, 
			 "Tried to instantiate unbound var",
			 tree);
	    return neu;
	}
	else if (tree instanceof Cons) {
	    Cons c = (Cons)tree;
	    return new Cons(instantiateTree(c.car()),
			    (LList)instantiateTree(c.cdr()));
	}
	else
	    return tree;
    }

    public Object instantiateTree(Object tree,
				  Function1 ifUnbound) {
	// Debug.noteln("instantiateTree(" + tree + ", " + ifUnbound + ")");
	if (tree instanceof ItemVar) {
	    ItemVar var = (ItemVar)tree;
	    Object val = get(var);
	    if (val == null)
		return ifUnbound.funcall(var);
	    else 
		return val;
	}
	else if (tree instanceof Cons) {
	    Cons c = (Cons)tree;
	    return new Cons(instantiateTree(c.car(), ifUnbound),
			    (LList)instantiateTree(c.cdr(), ifUnbound));
	}
	else
	    return tree;
    }

}

// Issues:
// * Does it make sense to have instantiateTree() here?

