package sdsi;

import sdsi.sexp.*;

/**
 * A simple TagExpression (what Morcos called SimpleTag).
 * These intersect by taking the longer of the two, with any
 * common elements themselves being intersected.
 *
 * @author jonh@cs.dartmouth.edu
 */

class TEList
	extends TESDSIObject {

	//	so we don't allow tags that look like
	//	((* set read write) file foo) ?
	// [jonh] Notice I make no effort in my own version of this
	// code to prevent that case.
	TagExpression[] tags;

	TEList(SexpList l)
		throws SexpParseException {
		super(l);
		int size = l.size();
		tags = new TagExpression[size];
		for (int i=0; i<size; i++) {
			tags[i] = TEParse.parse(l.elementAt(i));
		}
	}

	TEList(TagExpression tags[]) {
		this.tags = tags;
		Sexp[] sexpary = new Sexp[tags.length];
		for (int i=0; i<tags.length; i++) {
			sexpary[i] = tags[i].getSexp();
		}
		srep = new SexpList(sexpary);
	}

	public TagExpression intersect(TagExpression otherTE) {
		if (otherTE instanceof TESpecial) {
			return otherTE.intersect(this);
		} else if (otherTE instanceof TEList) {
			// all elements that appear in both lists must agree
			// (intersect meaningfully); extra elements copied from
			// longer list (they're intersecting with a virtual (*).)

			TEList otherList = (TEList) otherTE;

			TEList shortList, longList;
			if (tags.length <= otherList.tags.length) {
				shortList = this;
				longList = otherList;
			} else {
				shortList = otherList;
				longList = this;
			}
			TagExpression outputTags[] =
				new TagExpression[longList.tags.length];
			for (int i=0; i<outputTags.length; i++) {
				if (i < shortList.tags.length) {
					outputTags[i] = shortList.tags[i]
						.intersect(longList.tags[i]);
					if (outputTags[i] instanceof TENull) {
						// a null intersection anywhere in the list
						// prevents any match with this list -- the
						// result is itself the null tag.
						return TENull.getNull();
					}
				} else {
					outputTags[i] = longList.tags[i];
				}
			}
			return new TEList(outputTags);
		} else if (otherTE instanceof TENull) {
			// null always intersects to null.
			return otherTE;
		} else if (otherTE instanceof TEByteString) {
			// I believe a bytestring is meant to be treated
			// differently, not "cast" to a one-item list.
			return TENull.getNull();
		} else {
			throw new RuntimeException("Got unknown TE type: "
				+otherTE.getClass());
		}
	}
}
