package x10.sncode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Constraint {
List<Term> terms;
public static final int CONSTANT = 0;
public static final int VAR = 1;
public static final int EQV = 2;
public static final int FIELD = 3;
public static final int FORMULA = 4;
public static class Field extends Term {
Term target;
int fieldRefIndex;
public Field(Term target, int fieldRefIndex) {
this.target = target;
this.fieldRefIndex = fieldRefIndex;
}
@Override
public int getKind() {
return FIELD;
}
public void write(ByteBuffer w) {
w.addInt(FIELD);
w.addInt(fieldRefIndex);
target.write(w);
}
public Term getTarget() {
return target;
}
public int getName() {
return fieldRefIndex;
}
}
public static class Formula extends Term {
int op;
Term[] children;
public Formula(int op, Term[] children) {
this.op = op;
this.children = children;
}
@Override
public int getKind() {
return FORMULA;
}
public void write(ByteBuffer w) {
w.addInt(FORMULA);
w.addInt(op);
w.addInt(children.length);
for (Term t : children) {
t.write(w);
}
}
public Term[] getArgs() {
return children;
}
public int getName() {
return op;
}
}
public static abstract class Term {
public abstract void write(ByteBuffer w);
public abstract int getKind();
}
public static class Constant extends Term {
int constantIndex;
public Constant(int constantIndex) {
this.constantIndex = constantIndex;
}
@Override
public int getKind() {
return CONSTANT;
}
public void write(ByteBuffer w) {
w.addInt(CONSTANT);
w.addInt(constantIndex);
}
public int getValue() {
return constantIndex;
}
}
public static class Var extends Term {
int op;
int nameIndex;
public Var(int op, int nameIndex) {
this.op = op;
this.nameIndex = nameIndex;
}
@Override
public int getKind() {
return op;
}
public void write(ByteBuffer w) {
w.addInt(op);
w.addInt(nameIndex);
}
public int getName() {
return nameIndex;
}
}
public Constraint(Term... t) {
terms = Arrays.asList(t);
}
public Constraint(ByteBuffer b, int offset, int len)
throws InvalidClassFileException {
b.seek(offset);
int numTerms = b.getCount();
terms = new ArrayList<Term>(numTerms);
for (int i = 0; i < numTerms; i++) {
Term t = readTerm(b);
terms.add(t);
}
if (b.offset() != offset + len)
throw new InvalidClassFileException(offset, "bad constraint");
}
public void write(ByteBuffer w) {
int offset = w.offset();
w.addLength(0);
w.addCount(terms.size());
for (Term t : terms) {
t.write(w);
}
w.setLength(offset, w.offset() - offset - 4);
}
private Term readTerm(ByteBuffer b) throws InvalidClassFileException {
int op = b.getCPIndex();
switch (op) {
case VAR:
case EQV: {
int index = b.getCPIndex();
return new Var(op, index);
}
case FIELD: {
int index = b.getCPIndex();
Term t = readTerm(b);
return new Field(t, index);
}
case CONSTANT: {
int index = b.getCPIndex();
return new Constant(index);
}
default: {
int numTerms = b.getCount();
int name = b.getCPIndex();
Term[] terms = new Term[numTerms];
for (int i = 0; i < terms.length; i++) {
Term t = readTerm(b);
terms[i] = t;
}
return new Formula(name, terms);
}
}
}
public List<Term> getTerms() {
return terms;
}
public void addTerm(Term t) {
terms.add(t);
}
}