--- /dev/null
+package MCC.IR;
+
+/**
+ * ArrayDescriptor
+ *
+ * wrapper descriptor for an internal field descriptor that
+ * allows arrays
+ */
+
+public class ArrayDescriptor extends FieldDescriptor {
+
+ FieldDescriptor fd;
+ Expr index;
+
+ public ArrayDescriptor(FieldDescriptor fd, Expr index) {
+ super(fd.getSymbol());
+ this.index = index;
+ this.fd = fd;
+ }
+
+ public FieldDescriptor getField() {
+ return fd;
+ }
+
+ public TypeDescriptor getType() {
+ return fd.getType();
+ }
+
+ public void setType(TypeDescriptor td) {
+ fd.setType(td);
+ }
+
+ public Expr getIndexBound() {
+ return index;
+ }
+
+ public Expr getBaseSizeExpr() {
+ throw new IRException();
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import MCC.State;
+
+public class BooleanLiteralExpr extends LiteralExpr {
+
+ boolean value;
+
+ public BooleanLiteralExpr(boolean value) {
+ this.value = value;
+ td = ReservedTypeDescriptor.INT;
+ }
+
+ public boolean getValue() {
+ return value;
+ }
+
+ public void generate(CodeWriter writer, VarDescriptor dest) {
+ writer.outputline("int " + dest.getSafeSymbol() + " = " + (value ? "1" : "0") + ";");
+ }
+
+ public void prettyPrint(PrettyPrinter pp) {
+ pp.output(value ? "true" : "false");
+ }
+
+ public TypeDescriptor typecheck(SemanticAnalyzer sa) {
+ td = ReservedTypeDescriptor.INT;
+ return td;
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class CastExpr extends Expr {
+
+ TypeDescriptor type;
+ Expr expr;
+
+ public CastExpr(TypeDescriptor type, Expr expr) {
+ this.type = type;
+ this.expr = expr;
+ }
+
+ public Set getRequiredDescriptors() {
+ return expr.getRequiredDescriptors();
+ }
+
+ public void generate(CodeWriter writer, VarDescriptor dest) {
+ VarDescriptor vd = VarDescriptor.makeNew("expr");
+ expr.generate(writer, vd);
+ writer.outputline("int " + dest.getSafeSymbol() + " = (int) " + vd.getSafeSymbol() + ";");
+ }
+
+ public void prettyPrint(PrettyPrinter pp) {
+ pp.output("cast(" + type.getSafeSymbol() + ", ");
+ expr.prettyPrint(pp);
+ pp.output(")");
+ }
+
+ public TypeDescriptor getType() {
+ return type;
+ }
+
+ public TypeDescriptor typecheck(SemanticAnalyzer sa) {
+ TypeDescriptor td = expr.typecheck(sa);
+
+ if (td == null) {
+ return null;
+ }
+
+ if (!type.isSubtypeOf(td)) {
+ sa.getErrorReporter().report(null, "Expression type '" + td.getSymbol() + "' is not a parent of the cast type '" + type.getSymbol() + "'");
+ return null;
+ }
+
+ this.td = type;
+ return type;
+ }
+
+}
+
+
+
+
+
+
+
+
--- /dev/null
+package MCC.IR;
+
+public interface CodeWriter extends PrettyPrinter{
+
+ public void outputline(String s);
+ public void indent();
+ public void unindent();
+
+ public SymbolTable getSymbolTable();
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class ComparisonPredicate extends Predicate {
+
+ public static final Comparison GT = new Comparison("GT");
+ public static final Comparison GE = new Comparison("GE");
+ public static final Comparison LT = new Comparison("LT");
+ public static final Comparison LE = new Comparison("LE");
+ public static final Comparison EQ = new Comparison("EQ");
+ private static final Comparison ALL[] = { GT, GE, LT, LE, EQ };
+
+ public static class Comparison {
+ private final String name;
+ private Comparison(String name) { this.name = name; }
+ public String toString() { return name; }
+ public static Comparison fromString(String name) {
+ if (name == null) {
+ throw new NullPointerException();
+ }
+
+ for (int i = 0; i < ALL.length; i++) {
+ if (name.equalsIgnoreCase(ALL[i].toString())) {
+ return ALL[i];
+ }
+ }
+
+ throw new IllegalArgumentException("Input not a valid comparison.");
+ }
+ }
+
+ Comparison comparison;
+ Expr left, right;
+
+ public ComparisonPredicate(String comparison, Expr left, Expr right) {
+ this.comparison = Comparison.fromString(comparison);
+ this.left = left;
+ this.right = right;
+ }
+
+ public Set getRequiredDescriptors() {
+ assert left != null;
+ assert right != null;
+ Set v = left.getRequiredDescriptors();
+ v.addAll(right.getRequiredDescriptors());
+ return v;
+ }
+
+}
+
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class Constraint {
+
+ private static int count = 1;
+
+ String label = null;
+ boolean crash = false;
+ SymbolTable st = new SymbolTable();
+ Vector quantifiers = new Vector();
+ LogicStatement logicstatement = null;
+
+ public Constraint() {
+ label = new String("c" + count++);
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public SymbolTable getSymbolTable() {
+ return st;
+ }
+
+ public void addQuantifier(Quantifier q) {
+ quantifiers.addElement(q);
+ }
+
+ public void setLogicStatement(LogicStatement ls) {
+ logicstatement = ls;
+ }
+
+ public LogicStatement getLogicStatement() {
+ return logicstatement;
+ }
+
+ public void setCrash(boolean crash) {
+ this.crash = crash;
+ }
+
+ public Iterator quantifiers() {
+ return quantifiers.iterator();
+ }
+
+ public Set getRequiredDescriptorsFromQuantifiers() {
+
+ HashSet topdescriptors = new HashSet();
+
+ for (int i = 0; i < quantifiers.size(); i++) {
+ Quantifier q = (Quantifier) quantifiers.elementAt(i);
+ topdescriptors.addAll(q.getRequiredDescriptors());
+ }
+
+ return SetDescriptor.expand(topdescriptors);
+ }
+
+ public Set getRequiredDescriptorsFromLogicStatement() {
+
+ HashSet topdescriptors = new HashSet();
+
+ topdescriptors.addAll(logicstatement.getRequiredDescriptors());
+
+ return SetDescriptor.expand(topdescriptors);
+ }
+
+ public Set getRequiredDescriptors() {
+ Set set = getRequiredDescriptorsFromQuantifiers();
+ set.addAll(getRequiredDescriptorsFromLogicStatement());
+ return set;
+ }
+
+}
+
--- /dev/null
+package MCC.IR;
+
+import MCC.State;
+import java.util.*;
+
+public class DependencyBuilder {
+
+ Hashtable constraintnodes = new Hashtable();
+ Hashtable rulenodes = new Hashtable();
+ State state;
+
+ public DependencyBuilder(State state) {
+ this.state = state;
+ }
+
+ public void calculate() {
+
+ /* reinitialize (clear) nodes */
+ constraintnodes = new Hashtable();
+ rulenodes = new Hashtable();
+
+ /* load up the rules and constraints */
+ Vector rules = state.vRules;
+ Vector constraints = state.vConstraints;
+
+ /* build up graph rulenodes (not edges yet) */
+ for (int i = 0; i < rules.size(); i++) {
+ Rule rule = (Rule) rules.elementAt(i);
+ assert rule != null;
+ assert rule.getLabel() != null;
+
+ Inclusion inclusion = rule.getInclusion();
+ Iterator targets = inclusion.getTargetDescriptors().iterator();
+ String additionallabel = new String();
+
+ if (targets.hasNext()) {
+ Descriptor d = (Descriptor)targets.next();
+ additionallabel = "\\n" + d.getSymbol();
+ }
+
+ GraphNode gn = new GraphNode(rule.getLabel(), rule.getLabel() + additionallabel, rule);
+ rulenodes.put(rule.getLabel(), gn);
+ }
+
+ /* build up graph constraintnodes (not edges yet) */
+ for (int i = 0; i < constraints.size(); i++) {
+ Constraint constraint = (Constraint) constraints.elementAt(i);
+ assert constraint != null;
+ assert constraint.getLabel() != null;
+ GraphNode gn = new GraphNode(constraint.getLabel(), constraint);
+ gn.setDotNodeParameters("shape=box");
+ constraintnodes.put(constraint.getLabel(), gn);
+ }
+
+ /* calculate rule->rule dependencies */
+ for (int i = 0; i < rules.size(); i++) {
+ Rule rule = (Rule) rules.elementAt(i);
+ GraphNode rulenode = (GraphNode) rulenodes.get(rule.getLabel());
+ Set requiredsymbols = rule.getRequiredDescriptors();
+
+ for (int j = 0; j < rules.size(); j++) {
+
+ if (j == i) {
+ continue;
+ }
+
+ Rule otherrule = (Rule) rules.elementAt(j);
+ Inclusion inclusion = otherrule.getInclusion();
+ Iterator targets = inclusion.getTargetDescriptors().iterator();
+ GraphNode otherrulenode = (GraphNode) rulenodes.get(otherrule.getLabel());
+
+ while (targets.hasNext()) {
+ Descriptor d = (Descriptor) targets.next();
+
+ if (requiredsymbols.contains(d)) { /* rule->rule dependency */
+ otherrulenode.addEdge(new GraphNode.Edge(d.getSymbol(), rulenode));
+ }
+ }
+ }
+ }
+
+ /* build constraint->rule dependencies */
+ for (int i = 0; i < constraints.size(); i++) {
+ Constraint constraint = (Constraint) constraints.elementAt(i);
+ GraphNode constraintnode = (GraphNode) constraintnodes.get(constraint.getLabel());
+ Set requiredsymbols = constraint.getRequiredDescriptorsFromLogicStatement();
+ Set requiredquantifiers = constraint.getRequiredDescriptorsFromQuantifiers();
+
+ for (int j = 0; j < rules.size(); j++) {
+ Rule otherrule = (Rule) rules.elementAt(j);
+ Inclusion inclusion = otherrule.getInclusion();
+ Iterator targets = inclusion.getTargetDescriptors().iterator();
+ GraphNode otherrulenode = (GraphNode) rulenodes.get(otherrule.getLabel());
+
+ while (targets.hasNext()) {
+ Descriptor d = (Descriptor) targets.next();
+
+ if (requiredsymbols.contains(d)) { /* logic->rule dependency */
+ GraphNode.Edge edge = new GraphNode.Edge(d.getSymbol(), constraintnode);
+ //edge.setDotNodeParameters("style=bold");
+ otherrulenode.addEdge(edge);
+ }
+
+ if (requiredquantifiers.contains(d)) { /* quantifier-> dependency */
+ GraphNode.Edge edge = new GraphNode.Edge(d.getSymbol(), constraintnode);
+ edge.setDotNodeParameters("style=dotted");
+ otherrulenode.addEdge(edge);
+ }
+ }
+ }
+ }
+
+ /* store results in state */
+ state.rulenodes = rulenodes;
+ state.constraintnodes = constraintnodes;
+ }
+
+ static class IntegerLattice {
+
+ boolean top;
+ boolean isNum;
+ int num;
+
+ public static final IntegerLattice TOP = new IntegerLattice(true);
+ public static final IntegerLattice BOT = new IntegerLattice(false);
+
+ private IntegerLattice(boolean top) {
+ this.top = top;
+ isNum = false;
+ }
+
+ public IntegerLattice(int num) {
+ isNum = true;
+ this.num = num;
+ }
+
+ }
+
+ public IntegerLattice setSize(SetDescriptor sd) {
+ String setname = sd.getSymbol();
+
+ if (setname.equals("Block")) {
+ return IntegerLattice.TOP;
+ } else if (setname.equals("UsedBlock")) {
+ return IntegerLattice.TOP;
+ } else if (setname.equals("FreeBlock")) {
+ return IntegerLattice.TOP;
+ } else if (setname.equals("Inode")) {
+ return IntegerLattice.TOP;
+ } else if (setname.equals("UsedInode")) {
+ return IntegerLattice.TOP;
+ } else if (setname.equals("FileInode")) {
+ return IntegerLattice.TOP;
+ } else if (setname.equals("DirectoryInode")) {
+ return new IntegerLattice(1);
+ } else if (setname.equals("RootDirectoryInode")) {
+ return new IntegerLattice(1);
+ } else if (setname.equals("SuperBlock")) {
+ return new IntegerLattice(1);
+ } else if (setname.equals("GroupBlock")) {
+ return new IntegerLattice(1);
+ } else if (setname.equals("FileDirectoryBlock")) {
+ return IntegerLattice.TOP;
+ } else if (setname.equals("InodeTableBlock")) {
+ return new IntegerLattice(1);
+ } else if (setname.equals("InodeBitmapBlock")) {
+ return new IntegerLattice(1);
+ } else if (setname.equals("BlockBitmapBlock")) {
+ return new IntegerLattice(1);
+ } else if (setname.equals("DirectoryBlock")) {
+ return new IntegerLattice(0);
+ } else if (setname.equals("FileBlock")) {
+ return IntegerLattice.TOP;
+ } else if (setname.equals("DirectoryEntry")) {
+ return IntegerLattice.TOP;
+ } else {
+ throw new IRException();
+ }
+
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+/**
+ * Descriptor
+ *
+ * represents a symbol in the language (var name, function name, etc).
+ */
+
+public abstract class Descriptor {
+
+ protected String name;
+ protected String safename;
+
+ public Descriptor(String name) {
+ this.name = name;
+ this.safename = "__" + name + "__";
+ }
+
+ protected Descriptor(String name, String safename) {
+ this.name = name;
+ this.safename = safename;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ public String getSymbol() {
+ return name;
+ }
+
+ public String getSafeSymbol() {
+ return safename;
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class DotExpr extends Expr {
+
+ Expr left;
+ String field;
+ Expr index;
+
+ public DotExpr(Expr left, String field, Expr index) {
+ this.left = left;
+ this.field = field;
+ this.index = index;
+ }
+
+ public Set getRequiredDescriptors() {
+ Set v = left.getRequiredDescriptors();
+
+ if (index != null) {
+ v.addAll(index.getRequiredDescriptors());
+ }
+
+ return v;
+ }
+
+ public void generate(CodeWriter writer, VarDescriptor dest) {
+ VarDescriptor leftd = VarDescriptor.makeNew("left");
+
+ writer.output("// " + leftd.getSafeSymbol() + " <-- ");
+ left.prettyPrint(writer);
+ writer.outputline("");
+
+ left.generate(writer, leftd);
+
+ writer.output("// " + leftd.getSafeSymbol() + " = ");
+ left.prettyPrint(writer);
+ writer.outputline("");
+
+
+ StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();
+ FieldDescriptor fd = struct.getField(field);
+ LabelDescriptor ld = struct.getLabel(field);
+ Expr intindex = index;
+ Expr offsetbits;
+
+ if (ld != null) { /* label */
+ assert fd == null;
+ fd = ld.getField();
+ assert fd != null;
+ assert intindex == null;
+ intindex = ld.getIndex();
+ }
+
+ // #ATTN#: getOffsetExpr needs to be called with the fielddescriptor obect that is in teh vector list
+ // this means that if the field is an arraydescriptor you have to call getOffsetExpr with the array
+ // descriptor not the underlying field descriptor
+
+ /* we calculate the offset in bits */
+ offsetbits = struct.getOffsetExpr(fd);
+
+ if (fd instanceof ArrayDescriptor) {
+ fd = ((ArrayDescriptor) fd).getField();
+ }
+
+ if (intindex != null) {
+ if (intindex instanceof IntegerLiteralExpr && ((IntegerLiteralExpr) intindex).getValue() == 0) {
+ /* short circuit for constant 0 */
+ } else {
+ Expr basesize = fd.getBaseSizeExpr();
+ offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, intindex));
+ }
+ }
+
+ final SymbolTable st = writer.getSymbolTable();
+ TypeDescriptor td = offsetbits.typecheck(new SemanticAnalyzer() {
+ public IRErrorReporter getErrorReporter() { throw new IRException("badness"); }
+ public SymbolTable getSymbolTable() { return st; }
+ });
+
+ if (td == null) {
+ throw new IRException();
+ } else if (td != ReservedTypeDescriptor.INT) {
+ throw new IRException();
+ }
+
+ // #TBD#: ptr's to bits and byte's and stuff are a little iffy...
+ // right now, a bit* is the same as a int* = short* = byte* (that is there
+ // is no post-derefernce mask)
+
+ if (offsetbits instanceof IntegerLiteralExpr) {
+ int offsetinbits = ((IntegerLiteralExpr) offsetbits).getValue();
+ int offset = offsetinbits >> 3; /* offset in bytes */
+
+ if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) {
+ int shift = offsetinbits - (offset << 3);
+ int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue());
+
+ /* type var = ((*(int *) (base + offset)) >> shift) & mask */
+ writer.outputline(getType().getGenerateType() + " " + dest.getSafeSymbol() +
+ " = ((*(int *)" +
+ "(" + leftd.getSafeSymbol() + " + " + offset + ")) " +
+ " >> " + shift + ") & 0x" + Integer.toHexString(mask) + ";");
+ } else { /* a structure address or a ptr! */
+ String ptr = fd.getPtr() ? "*(int *)" : "";
+ /* type var = [*(int *)] (base + offset) */
+ writer.outputline(getType().getGenerateType() + " " + dest.getSafeSymbol() +
+ " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset + ");");
+ }
+ } else { /* offset in bits is an expression that must be generated */
+ VarDescriptor ob = VarDescriptor.makeNew("offsetinbits");
+ writer.output("// " + ob.getSafeSymbol() + " <-- ");
+ offsetbits.prettyPrint(writer);
+ writer.outputline("");
+ offsetbits.generate(writer, ob);
+ writer.output("// " + ob.getSafeSymbol() + " = ");
+ offsetbits.prettyPrint(writer);
+ writer.outputline("");
+
+ /* derive offset in bytes */
+ VarDescriptor offset = VarDescriptor.makeNew("offset");
+ writer.outputline("int " + offset.getSafeSymbol() + " = " + ob.getSafeSymbol() + " >> 3;");
+
+ if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) {
+ VarDescriptor shift = VarDescriptor.makeNew("shift");
+ writer.outputline("int " + shift.getSafeSymbol() + " = " + ob.getSafeSymbol() +
+ " - (" + offset.getSafeSymbol() + " << 3);");
+ int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue());
+
+ /* type var = ((*(int *) (base + offset)) >> shift) & mask */
+ writer.outputline(getType().getGenerateType() + " " + dest.getSafeSymbol() +
+ " = ((*(int *)" +
+ "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")) " +
+ " >> " + shift.getSafeSymbol() + ") & 0x" + Integer.toHexString(mask) + ";");
+ } else { /* a structure address or a ptr */
+ String ptr = fd.getPtr() ? "*(int *)" : "";
+ /* type var = [*(int *)] (base + offset) */
+ writer.outputline(getType().getGenerateType() + " " + dest.getSafeSymbol() +
+ " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ");");
+ }
+ }
+ }
+
+ private int bitmask(int bits) {
+ int mask = 0;
+
+ for (int i = 0; i < bits; i++) {
+ mask <<= 1;
+ mask += 1;
+ }
+
+ return mask;
+ }
+
+ public void prettyPrint(PrettyPrinter pp) {
+ left.prettyPrint(pp);
+ pp.output("." + field);
+ if (index != null) {
+ pp.output("[");
+ index.prettyPrint(pp);
+ pp.output("]");
+ }
+ }
+
+ public TypeDescriptor typecheck(SemanticAnalyzer sa) {
+ TypeDescriptor lefttype = left.typecheck(sa);
+ TypeDescriptor indextype = index == null ? null : index.typecheck(sa);
+
+ if ((lefttype == null) || (index != null && indextype == null)) {
+ return null;
+ }
+
+ if (indextype != null) {
+ if (indextype != ReservedTypeDescriptor.INT) {
+ sa.getErrorReporter().report(null, "Index must be of type 'int' not '" + indextype.getSymbol() + "'");
+ return null;
+ }
+ }
+
+ if (lefttype instanceof StructureTypeDescriptor) {
+ StructureTypeDescriptor struct = (StructureTypeDescriptor) lefttype;
+ FieldDescriptor fd = struct.getField(field);
+ LabelDescriptor ld = struct.getLabel(field);
+
+ if (fd != null) { /* field */
+ assert ld == null;
+
+ if (indextype == null && fd instanceof ArrayDescriptor) {
+ sa.getErrorReporter().report(null, "Must specify an index what accessing array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
+ return null;
+ } else if (indextype != null && !(fd instanceof ArrayDescriptor)) {
+ sa.getErrorReporter().report(null, "Cannot specify an index when accessing non-array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
+ return null;
+ }
+
+ this.td = fd.getType();
+ } else if (ld != null) { /* label */
+ assert fd == null;
+
+ if (index != null) {
+ sa.getErrorReporter().report(null, "A label cannot be accessed as an array");
+ return null;
+ }
+
+ this.td = ld.getType();
+ } else {
+ sa.getErrorReporter().report(null, "No such field or label '" + field + "' in structure '" + struct.getSymbol() + "'");
+ return null;
+ }
+
+ /* we promote bit, byte and short to integer types */
+ if (this.td == ReservedTypeDescriptor.BIT ||
+ this.td == ReservedTypeDescriptor.BYTE ||
+ this.td == ReservedTypeDescriptor.SHORT) {
+ this.td = ReservedTypeDescriptor.INT;
+ }
+
+ return this.td;
+ } else {
+ sa.getErrorReporter().report(null, "Left hand side of . expression must be a structure type, not '" + lefttype.getSymbol() + "'");
+ return null;
+ }
+
+
+ }
+
+}
+
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class ElementOfExpr extends Expr {
+
+ Expr element;
+ SetDescriptor set;
+
+ public ElementOfExpr(Expr element, SetDescriptor set) {
+ if (element == null || set == null) {
+ throw new NullPointerException();
+ }
+
+ this.element = element;
+ this.set = set;
+ }
+
+ public Set getRequiredDescriptors() {
+ Set v = element.getRequiredDescriptors();
+ v.add(set);
+ return v;
+ }
+
+ public void generate(CodeWriter writer, VarDescriptor dest) {
+ VarDescriptor ed = VarDescriptor.makeNew("element");
+ element.generate(writer, ed);
+ writer.outputline("int " + dest.getSafeSymbol() + " = " +
+ set.getSafeSymbol() + "_hash->contains(" + ed.getSafeSymbol() + ");");
+ }
+
+ public void prettyPrint(PrettyPrinter pp) {
+ element.prettyPrint(pp);
+ pp.output(" in? " + set.getSafeSymbol());
+ }
+
+ public TypeDescriptor typecheck(SemanticAnalyzer sa) {
+ TypeDescriptor td = element.typecheck(sa);
+
+ if (td == null) {
+ return null;
+ }
+
+ TypeDescriptor settype = set.getType();
+
+ if (!td.equals(settype)) {
+ sa.getErrorReporter().report(null, "Type mismatch: attempting to test for types '" + td.getSymbol() + "' in set of type '" + settype.getSymbol() + "'");
+ return null;
+ }
+
+ this.td = ReservedTypeDescriptor.INT;
+ return this.td;
+ }
+
+}
+
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public abstract class Expr {
+
+ TypeDescriptor td = null;
+
+ public Expr() {}
+
+ public abstract Set getRequiredDescriptors();
+
+ public abstract void generate(CodeWriter writer, VarDescriptor dest);
+
+ public TypeDescriptor getType() {
+ assert td != null : toString();
+ return td;
+ }
+
+ public abstract TypeDescriptor typecheck(SemanticAnalyzer sa);
+
+ public abstract void prettyPrint(PrettyPrinter pp);
+
+}
--- /dev/null
+/**
+ * FieldDescriptor
+ *
+ * represents a field of a type
+ */
+
+package MCC.IR;
+
+public class FieldDescriptor extends Descriptor {
+
+ TypeDescriptor type;
+ boolean ptr;
+
+ public FieldDescriptor(String name) {
+ super(name);
+ }
+
+ public TypeDescriptor getType() {
+ assert type != null;
+ return type;
+ }
+
+ public void setType(TypeDescriptor td) {
+ assert td != null;
+ type = td;
+ }
+
+ public void setPtr(boolean ptr) {
+ this.ptr = ptr;
+ }
+
+ public boolean getPtr() {
+ return ptr;
+ }
+
+ public Expr getBaseSizeExpr() {
+ if (ptr) { /* ptrs are 32bits */
+ return new IntegerLiteralExpr(32);
+ } else {
+ return type.getSizeExpr();
+ }
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class ForQuantifier extends Quantifier {
+
+ VarDescriptor var = null;
+ Expr lower = null;
+ Expr upper = null;
+
+ public ForQuantifier() {}
+
+ public void setVar(VarDescriptor vd) {
+ this.var = vd;
+ }
+
+ public void setBounds(Expr lower, Expr upper) {
+ this.lower = lower;
+ this.upper = upper;
+ }
+
+ public Set getRequiredDescriptors() {
+ return new HashSet();
+ }
+
+ public String toString() {
+ return "for quantifier " + var.getSymbol() + " = " + lower + " to " + upper;
+ }
+
+ public void generate_open(CodeWriter writer) {
+ VarDescriptor ld = VarDescriptor.makeNew();
+ VarDescriptor ud = VarDescriptor.makeNew();
+ lower.generate(writer, ld);
+ upper.generate(writer, ud);
+
+ writer.outputline("for (int " + var.getSafeSymbol() + " = " + ld.getSafeSymbol() + "; " + var.getSafeSymbol() + " <= " + ud.getSafeSymbol() + "; " + var.getSafeSymbol() + "++) {");
+ writer.indent();
+ }
+
+ public boolean typecheck(SemanticAnalyzer sa) {
+ TypeDescriptor lt = lower.typecheck(sa);
+ TypeDescriptor ut = upper.typecheck(sa);
+
+ if (lt == null || ut == null) {
+ return false;
+ }
+
+ boolean ok = true;
+
+ if (lt != ReservedTypeDescriptor.INT) {
+ sa.getErrorReporter().report(null, "Lower bound of for quantifier must be of type 'int'");
+ ok = false;
+ }
+
+ if (ut != ReservedTypeDescriptor.INT) {
+ sa.getErrorReporter().report(null, "Upper bound of for quantifier must be of type 'int'");
+ ok = false;
+ }
+
+ return ok;
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+import java.io.*;
+
+public class GraphNode {
+
+ public static boolean useEdgeLabels;
+
+ /* NodeStatus enumeration pattern ***********/
+
+ public static final NodeStatus UNVISITED = new NodeStatus("UNVISITED");
+ public static final NodeStatus PROCESSING = new NodeStatus("PROCESSING");
+ public static final NodeStatus FINISHED = new NodeStatus("FINISHED");
+
+ public static class NodeStatus {
+ private static String name;
+ private NodeStatus(String name) { this.name = name; }
+ public String toString() { return name; }
+ }
+
+ /* Edge *****************/
+
+ public static class Edge {
+
+ private String label;
+ private GraphNode target;
+ private String dotnodeparams = new String();
+
+ public Edge(String label, GraphNode target) {
+ this.label = label;
+ this.target = target;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public GraphNode getTarget() {
+ return target;
+ }
+
+ public void setDotNodeParameters(String param) {
+ if (param == null) {
+ throw new NullPointerException();
+ }
+ if (param.length() > 0) {
+ dotnodeparams = "," + param;
+ } else {
+ dotnodeparams = new String();
+ }
+ }
+
+ }
+
+ int discoverytime = -1;
+ int finishingtime = -1; /* used for searches */
+ Vector edges = new Vector();
+ String nodelabel;
+ String textlabel;
+ NodeStatus status = UNVISITED;
+ String dotnodeparams = new String();
+ Object owner = null;
+
+ public GraphNode(String label) {
+ this.nodelabel = label;
+ this.textlabel = label;
+ }
+
+ public GraphNode(String label, Object owner) {
+ this.nodelabel = label;
+ this.textlabel = label;
+ this.owner = owner;
+ }
+
+ public GraphNode(String label, String textlabel, Object owner) {
+ this.nodelabel = label;
+ this.textlabel = textlabel;
+ this.owner = owner;
+ }
+
+ public Object getOwner() {
+ return owner;
+ }
+
+ public void setDotNodeParameters(String param) {
+ if (param == null) {
+ throw new NullPointerException();
+ }
+ if (param.length() > 0) {
+ dotnodeparams = "," + param;
+ } else {
+ dotnodeparams = new String();
+ }
+ }
+
+ public void setStatus(NodeStatus status) {
+ if (status == null) {
+ throw new NullPointerException();
+ }
+ this.status = status;
+ }
+
+ public String getLabel() {
+ return nodelabel;
+ }
+
+ public String getTextLabel() {
+ return textlabel;
+ }
+
+ public NodeStatus getStatus() {
+ return this.status;
+ }
+
+ public Iterator edges() {
+ return edges.iterator();
+ }
+
+ public void addEdge(Edge newedge) {
+ edges.addElement(newedge);
+ }
+
+ public void reset() {
+ discoverytime = -1;
+ finishingtime = -1;
+ status = UNVISITED;
+ }
+
+ public void discover(int time) {
+ discoverytime = time++;
+ status = PROCESSING;
+ }
+
+ public void finish(int time) {
+ assert status == PROCESSING;
+ finishingtime = time++;
+ status = FINISHED;
+ }
+
+ public int getFinishingTime() {
+ return finishingtime;
+ }
+
+ public static class DOTVisitor {
+
+ java.io.PrintWriter output;
+ int tokennumber;
+ int color;
+
+ private DOTVisitor(java.io.OutputStream output) {
+ tokennumber = 0;
+ color = 0;
+ this.output = new java.io.PrintWriter(output, true);
+ }
+
+ private String getNewID(String name) {
+ tokennumber = tokennumber + 1;
+ return new String (name+tokennumber);
+ }
+
+ Collection nodes;
+
+ public static void visit(java.io.OutputStream output, Collection nodes) {
+ DOTVisitor visitor = new DOTVisitor(output);
+ visitor.nodes = nodes;
+ visitor.make();
+
+ }
+
+ private void make() {
+ output.println("digraph dotvisitor {");
+ output.println("\trotate=90;");
+ output.println("\tpage=\"8.5,11\";");
+ output.println("\tnslimit=1000.0;");
+ output.println("\tnslimit1=1000.0;");
+ output.println("\tmclimit=1000.0;");
+ output.println("\tremincross=true;");
+ output.println("\tnode [fontsize=10,height=\"0.1\", width=\"0.1\"];");
+ output.println("\tedge [fontsize=6];");
+
+ traverse();
+
+ output.println("}\n");
+ }
+
+ private void traverse() {
+ Iterator i = nodes.iterator();
+ while (i.hasNext()) {
+ GraphNode gn = (GraphNode) i.next();
+ Iterator edges = gn.edges();
+ String label = gn.getTextLabel(); // + " [" + gn.discoverytime + "," + gn.finishingtime + "];";
+ output.println("\t" + gn.getLabel() + " [label=\"" + label + "\"" + gn.dotnodeparams + "];");
+
+ while (edges.hasNext()) {
+ Edge edge = (Edge) edges.next();
+ GraphNode node = edge.getTarget();
+ String edgelabel = useEdgeLabels ? "label=\"" + edge.getLabel() + "\"" : "label=\"\"";
+ output.println("\t" + gn.getLabel() + " -> " + node.getLabel() + " [" + edgelabel + edge.dotnodeparams + "];");
+ }
+ }
+ }
+ }
+
+ /**
+ * DFS encapsulates the depth first search algorithm
+ */
+ public static class DFS {
+
+ int time = 0;
+ Collection nodes;
+
+ private DFS(Collection nodes) {
+ this.nodes = nodes;
+ }
+
+ public static void depthFirstSearch(Collection nodes) {
+ if (nodes == null) {
+ throw new NullPointerException();
+ }
+
+ DFS dfs = new DFS(nodes);
+ dfs.go();
+ }
+
+ private void go() {
+ Iterator i;
+ time = 0;
+
+ i = nodes.iterator();
+ while (i.hasNext()) {
+ GraphNode gn = (GraphNode) i.next();
+ gn.reset();
+ }
+
+ i = nodes.iterator();
+ while (i.hasNext()) {
+ GraphNode gn = (GraphNode) i.next();
+ assert gn.getStatus() != PROCESSING;
+ if (gn.getStatus() == UNVISITED) {
+ dfs(gn);
+ }
+ }
+ }
+
+ private void dfs(GraphNode gn) {
+ gn.discover(time++);
+ Iterator edges = gn.edges();
+
+ while (edges.hasNext()) {
+ Edge edge = (Edge) edges.next();
+ GraphNode node = edge.getTarget();
+ if (node.getStatus() == UNVISITED) {
+ dfs(node);
+ }
+ }
+
+ gn.finish(time++);
+ }
+
+ } /* end DFS */
+
+}
--- /dev/null
+package MCC.IR;
+
+public interface IRErrorReporter {
+ public void report(ParseNode v, String s);
+ public void warn(ParseNode v, String s);
+ public void setFilename(String filename);
+}
--- /dev/null
+package MCC.IR;
+
+/**
+ * If an exception condition occurs while building an IR, an IRException
+ * object is thrown.
+ */
+
+public class IRException extends java.lang.RuntimeException
+{
+ /**
+ * @param reason reason for exception
+ */
+ public IRException(String reason)
+ {
+ super(reason);
+ }
+
+ public IRException()
+ {
+ super("IR ERROR");
+ }
+}
+
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class ImageSetExpr extends SetExpr {
+
+ public static final boolean INVERSE = true;
+
+ VarDescriptor vd;
+ RelationDescriptor rd;
+ boolean inverse;
+
+ public ImageSetExpr(VarDescriptor vd, RelationDescriptor rd) {
+ this.vd = vd;
+ this.rd = rd;
+ this.inverse = false;
+ }
+
+ public ImageSetExpr(boolean inverse, VarDescriptor vd, RelationDescriptor rd) {
+ this.vd = vd;
+ this.rd = rd;
+ this.inverse = inverse;
+ }
+
+ public Set getRequiredDescriptors() {
+ HashSet v = new HashSet();
+ v.add(rd);
+ return v;
+ }
+
+ public void generate(CodeWriter writer, VarDescriptor vd) {
+ throw new IRException("not supported");
+ }
+
+ public void prettyPrint(PrettyPrinter pp) {
+ throw new IRException("not supported");
+ }
+
+ public TypeDescriptor typecheck(SemanticAnalyzer sa) {
+ throw new IRException("not supported");
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public abstract class Inclusion {
+
+ protected Inclusion() {}
+
+ public abstract Set getTargetDescriptors();
+
+ public abstract Set getRequiredDescriptors();
+
+ public abstract void generate(CodeWriter writer);
+
+ public abstract boolean typecheck(SemanticAnalyzer sa);
+
+}
+
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class InclusionPredicate extends Predicate {
+
+ VarDescriptor var;
+ SetExpr setexpr;
+
+ public InclusionPredicate(VarDescriptor var, SetExpr setexpr) {
+ if (var == null) {
+ throw new NullPointerException();
+ }
+
+ if (setexpr == null) {
+ throw new NullPointerException();
+ }
+
+ this.var = var;
+ this.setexpr = setexpr;
+ }
+
+ public Set getRequiredDescriptors() {
+ return setexpr.getRequiredDescriptors();
+ }
+
+}
+
--- /dev/null
+package MCC.IR;
+
+public class IntegerLiteralExpr extends LiteralExpr {
+
+ int value;
+
+ public IntegerLiteralExpr(int value) {
+ this.value = value;
+ td = ReservedTypeDescriptor.INT;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public void generate(CodeWriter writer, VarDescriptor dest) {
+ writer.outputline("int " + dest.getSafeSymbol() + " = " + value + ";");
+ }
+
+ public void prettyPrint(PrettyPrinter pp) {
+ pp.output("" + value);
+ }
+
+ public TypeDescriptor typecheck(SemanticAnalyzer sa) {
+ td = ReservedTypeDescriptor.INT;
+ return td;
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+/**
+ * LabelDescriptor
+ *
+ * a label descriptor represents a label in a structure which is just
+ * a shorthand notation for another field
+ */
+
+public class LabelDescriptor extends FieldDescriptor {
+
+ FieldDescriptor fd;
+ Expr index;
+
+ public LabelDescriptor(String name) {
+ super(name);
+ index = null;
+ }
+
+ public FieldDescriptor getField() {
+ return fd;
+ }
+
+ public void setField(FieldDescriptor fd) {
+ this.fd = fd;
+ }
+
+ public Expr getIndex() {
+ return index;
+ }
+
+ public void setIndex(Expr index) {
+ this.index = index;
+ }
+
+ public Expr getBaseSizeExpr() {
+ throw new IRException();
+ }
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public abstract class LiteralExpr extends Expr {
+
+ public Set getRequiredDescriptors() {
+ return new HashSet();
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class LogicStatement {
+
+ public static final Operation AND = new Operation("AND");
+ public static final Operation OR = new Operation("OR");
+ public static final Operation NOT = new Operation("NOT");
+
+ public static class Operation {
+ private final String name;
+ private Operation(String opname) { name = opname; }
+ public String toString() { return name; }
+ }
+
+ Operation op;
+ LogicStatement left;
+ LogicStatement right;
+
+ public LogicStatement(Operation op, LogicStatement left, LogicStatement right) {
+ if (op == NOT) {
+ throw new IllegalArgumentException("Must be a AND or OR expression.");
+ }
+
+ this.op = op;
+ this.left = left;
+ this.right = right;
+ }
+
+ public LogicStatement(Operation op, LogicStatement left) {
+ if (op != NOT) {
+ throw new IllegalArgumentException("Must be a NOT expression.");
+ }
+
+ this.op = op;
+ this.left = left;
+ this.right = null;
+ }
+
+ protected LogicStatement() {
+ this.op = null;
+ this.left = null;
+ this.right = null;
+ }
+
+ public Set getRequiredDescriptors() {
+ Set v = left.getRequiredDescriptors();
+ if (right != null) {
+ v.addAll(right.getRequiredDescriptors());
+ }
+ return v;
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+/**
+ * MissingSetDescriptor
+ *
+ * represents a set in the model space
+ */
+
+import java.util.*;
+
+public class MissingSetDescriptor extends SetDescriptor {
+
+ public MissingSetDescriptor(String name) {
+ super(name);
+ }
+
+ public boolean isPartition() {
+ throw new IRException();
+ }
+
+ public void isPartition(boolean newvalue) {
+ throw new IRException();
+ }
+
+ public void setType(TypeDescriptor td) {
+ throw new IRException();
+ }
+
+ public TypeDescriptor getType() {
+ throw new IRException();
+ }
+
+ public void addSubset(SetDescriptor sd) {
+ throw new IRException();
+ }
+
+ public Vector getSubsets() {
+ throw new IRException();
+ }
+}
--- /dev/null
+package MCC.IR;
+
+/**
+ * MissingTypeDescriptor
+ *
+ * a placeholder for type descriptors that haven't been found yet
+ */
+
+public class MissingTypeDescriptor extends TypeDescriptor {
+
+ public MissingTypeDescriptor(String name) {
+ super(name);
+ }
+
+ public Expr getSizeExpr() {
+ throw new IRException("invalid");
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.io.*;
+import java.util.*;
+import MCC.State;
+
+public class NaiveGenerator {
+
+ State state;
+ java.io.PrintWriter output = null;
+
+ public NaiveGenerator(State state) {
+ this.state = state;
+ }
+
+ public void generate(java.io.OutputStream output) {
+ this.output = new java.io.PrintWriter(output, true);
+
+ generate_hashtables();
+ generate_rules();
+ generate_implicit_checks();
+ generate_checks();
+
+ }
+
+ private void generate_hashtables() {
+
+ CodeWriter cr = new CodeWriter() {
+
+ int indent = 0;
+ public void indent() { indent++; }
+ public void unindent() { indent--; assert indent >= 0; }
+ private void doindent() {
+ for (int i = 0; i < indent; i++) {
+ output.print(" ");
+ }
+ }
+ public void outputline(String s) {
+ doindent();
+ output.println(s);
+ }
+ public void output(String s) { throw new IRException(); }
+ public SymbolTable getSymbolTable() { throw new IRException(); }
+ };
+
+ cr.outputline("// creating hashtables ");
+
+ /* build all the hashtables */
+ Hashtable hashtables = new Hashtable();
+
+ /* build sets */
+ Iterator sets = state.stSets.descriptors();
+
+ /* first pass create all the hash tables */
+ while (sets.hasNext()) {
+ SetDescriptor set = (SetDescriptor) sets.next();
+ cr.outputline("SimpleHash* " + set.getSafeSymbol() + "_hash = new SimpleHash();");
+ }
+
+ /* second pass build relationships between hashtables */
+ sets = state.stSets.descriptors();
+
+ while (sets.hasNext()) {
+ SetDescriptor set = (SetDescriptor) sets.next();
+ Iterator subsets = set.subsets();
+
+ while (subsets.hasNext()) {
+ SetDescriptor subset = (SetDescriptor) subsets.next();
+ cr.outputline(subset.getSafeSymbol() + "_hash->addParent(" + set.getSafeSymbol() + "_hash);");
+ }
+ }
+
+ /* build relations */
+ Iterator relations = state.stRelations.descriptors();
+
+ /* first pass create all the hash tables */
+ while (relations.hasNext()) {
+ RelationDescriptor relation = (RelationDescriptor) relations.next();
+ cr.outputline("SimpleHash* " + relation.getSafeSymbol() + "_hash = new SimpleHash();");
+ }
+
+ cr.outputline("");
+ cr.outputline("");
+
+ }
+
+ private void generate_rules() {
+
+ /* first we must sort the rules */
+ GraphNode.DFS.depthFirstSearch(state.rulenodes.values());
+
+ TreeSet topologicalsort = new TreeSet(new Comparator() {
+ public boolean equals(Object obj) { return false; }
+ public int compare(Object o1, Object o2) {
+ GraphNode g1 = (GraphNode) o1;
+ GraphNode g2 = (GraphNode) o2;
+ return g2.getFinishingTime() - g1.getFinishingTime();
+ }
+ });
+
+ topologicalsort.addAll(state.rulenodes.values());
+
+ /* build all the rules */
+ Iterator rules = topologicalsort.iterator();
+
+ while (rules.hasNext()) {
+
+ GraphNode rulenode = (GraphNode) rules.next();
+ Rule rule = (Rule) rulenode.getOwner();
+
+ {
+
+ final SymbolTable st = rule.getSymbolTable();
+
+ CodeWriter cr = new CodeWriter() {
+ boolean linestarted = false;
+ int indent = 0;
+ public void indent() { indent++; }
+ public void unindent() { indent--; assert indent >= 0; }
+ private void doindent() {
+ for (int i = 0; i < indent; i++) {
+ output.print(" ");
+ }
+ linestarted = true;
+ }
+ public void outputline(String s) {
+ if (!linestarted) {
+ doindent();
+ }
+ output.println(s);
+ linestarted = false;
+ }
+ public void output(String s) {
+ if (!linestarted) {
+ doindent();
+ }
+ output.print(s);
+ output.flush();
+ }
+ public SymbolTable getSymbolTable() { return st; }
+ };
+
+ cr.outputline("// build " + rule.getLabel());
+ cr.outputline("{");
+ cr.indent();
+
+ ListIterator quantifiers = rule.quantifiers();
+
+ while (quantifiers.hasNext()) {
+ Quantifier quantifier = (Quantifier) quantifiers.next();
+ quantifier.generate_open(cr);
+ }
+
+ /* pretty print! */
+ cr.output("//");
+ rule.getGuardExpr().prettyPrint(cr);
+ cr.outputline("");
+
+ /* now we have to generate the guard test */
+
+ VarDescriptor guardval = VarDescriptor.makeNew();
+ rule.getGuardExpr().generate(cr, guardval);
+
+ cr.outputline("if (" + guardval.getSafeSymbol() + ") {");
+
+ cr.indent();
+
+ /* now we have to generate the inclusion code */
+ rule.getInclusion().generate(cr);
+
+ cr.unindent();
+
+ cr.outputline("}");
+
+ while (quantifiers.hasPrevious()) {
+ Quantifier quantifier = (Quantifier) quantifiers.previous();
+ cr.unindent();
+ cr.outputline("}");
+ }
+
+ cr.unindent();
+ cr.outputline("}");
+ cr.outputline("");
+ cr.outputline("");
+ }
+ }
+
+ }
+
+ private void generate_implicit_checks() {
+
+ /* do post checks */
+ //output.println("check to make sure all relations are well typed");
+ //output.println("check multiplicity");
+
+ }
+
+ private void generate_checks() {
+
+ /* do constraint checks */
+ Vector constraints = state.vConstraints;
+
+ for (int i = 0; i < constraints.size(); i++) {
+ //output.println("check constraint " + (i + 1));
+ }
+
+ //output.println("report problems");
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class OpExpr extends Expr {
+
+ Expr left;
+ Expr right;
+ Opcode opcode;
+
+ public OpExpr(Opcode opcode, Expr left, Expr right) {
+ this.opcode = opcode;
+ this.left = left;
+ this.right = right;
+
+ assert (right == null && opcode == Opcode.NOT) || (right != null);
+ }
+
+ public Set getRequiredDescriptors() {
+ Set v = left.getRequiredDescriptors();
+
+ if (right != null) {
+ v.addAll(right.getRequiredDescriptors());
+ }
+
+ return v;
+ }
+
+ public void generate(CodeWriter writer, VarDescriptor dest) {
+ VarDescriptor ld = VarDescriptor.makeNew("leftop");
+ left.generate(writer, ld);
+ VarDescriptor rd = null;
+
+ if (right != null) {
+ rd = VarDescriptor.makeNew("rightop");
+ right.generate(writer, rd);
+ }
+
+ String code;
+ if (opcode != Opcode.NOT) { /* two operands */
+ assert rd != null;
+ writer.outputline("int " + dest.getSafeSymbol() + " = " +
+ ld.getSafeSymbol() + " " + opcode.toString() + " " + rd.getSafeSymbol() + ";");
+ } else {
+ writer.outputline("int " + dest.getSafeSymbol() + " = !" + ld.getSafeSymbol() + ";");
+ }
+ }
+
+ public void prettyPrint(PrettyPrinter pp) {
+ if (opcode == Opcode.NOT) {
+ pp.output("!");
+ left.prettyPrint(pp);
+ } else {
+ left.prettyPrint(pp);
+ pp.output(" " + opcode.toString() + " ");
+ assert right != null;
+ right.prettyPrint(pp);
+ }
+ }
+
+ public TypeDescriptor typecheck(SemanticAnalyzer sa) {
+ TypeDescriptor lt = left.typecheck(sa);
+ TypeDescriptor rt = right == null ? null : right.typecheck(sa);
+
+ if (lt == null) {
+ return null;
+ } else if (right != null && rt == null) {
+ return null;
+ }
+
+ boolean ok = true;
+
+ if (lt != ReservedTypeDescriptor.INT) {
+ sa.getErrorReporter().report(null, "Left hand side of expression is of type '" + lt.getSymbol() + "' but must be type 'int'");
+ ok = false;
+ }
+
+ if (right != null) {
+ if (rt != ReservedTypeDescriptor.INT) {
+ sa.getErrorReporter().report(null, "Right hand side of expression is of type '" + rt.getSymbol() + "' but must be type 'int'");
+ ok = false;
+ }
+ }
+
+ if (!ok) {
+ return null;
+ }
+
+ this.td = ReservedTypeDescriptor.INT;
+ return this.td;
+ }
+
+}
+
+
+
+
+
--- /dev/null
+package MCC.IR;
+
+public class Opcode {
+
+ private final String name;
+ private Opcode(String name) { this.name = name; }
+
+ public String toString() { return name; }
+
+ public static final Opcode ADD = new Opcode("+");
+ public static final Opcode SUB = new Opcode("-");
+ public static final Opcode MULT = new Opcode("*");
+ public static final Opcode DIV = new Opcode("/");
+
+ public static final Opcode GT = new Opcode(">");
+ public static final Opcode GE = new Opcode(">=");
+ public static final Opcode LT = new Opcode("<");
+ public static final Opcode LE = new Opcode("<=");
+
+ public static final Opcode EQ = new Opcode("==");
+ public static final Opcode NE = new Opcode("!=");
+
+ public static final Opcode AND = new Opcode("&&");
+ public static final Opcode OR = new Opcode("||");
+ public static final Opcode NOT = new Opcode("!");
+
+}
--- /dev/null
+/*
+
+ Class: ParseNode
+ Author: Dan Roy
+ Purpose: ParseNode is used to represent a parse production
+
+*/
+
+package MCC.IR;
+
+import java.util.*;
+
+public class ParseNode implements Walkable {
+
+ private String label;
+ private ParseNode parent;
+ private ParseNodeVector children;
+ private int line;
+
+ //private SymbolTable st;
+
+ public ParseNode(String label) {
+ this.label = label;
+ this.line = -1;
+ this.parent = null;
+ children = new ParseNodeVector();
+ }
+
+ public ParseNode ( String label, int line ) {
+ this.label = label;
+ this.line = line;
+ this.parent = null;
+ children = new ParseNodeVector();
+ }
+
+ public void setLabel( String label ) {
+ this.label = label;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ /*
+ public void setSymbolTable(SymbolTable st) {
+ if (st == null) {
+ throw new IRException("symboltable is null!");
+ }
+ this.st = st;
+ }
+
+ public SymbolTable getSymbolTable() {
+ if (st == null) {
+ if (parent != null) {
+ return parent.getSymbolTable();
+ } else {
+ return null;
+ }
+ } else {
+ return st;
+ }
+ }
+ */
+
+ public int getLine() {
+ if (line >= 0) {
+ return line;
+ } else {
+ if (parent != null) {
+ return parent.getLine();
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ public void setParent( ParseNode parent ) {
+ this.parent = parent;
+ }
+
+ public ParseNode getParent() {
+ return parent;
+ }
+
+ public ParseNode insertChild(ParseNode child) {
+ if (child == null) {
+ throw new NullPointerException("Can't add null node to parse tree");
+ }
+
+ children.insertElementAt(child, 0);
+ child.setParent(this);
+ return child;
+ }
+
+ public ParseNode insertChild(String newlabel) {
+ ParseNode child = new ParseNode(newlabel, -1);
+ return insertChild(child);
+ }
+
+ public ParseNode addChild( ParseNode child ) {
+
+ if (child == null)
+ throw new NullPointerException("Can't add null node to parse tree");
+
+ children.addElement (child);
+ child.setParent(this);
+ return child;
+ }
+
+ public ParseNode addChild( String newlabel ) {
+
+ ParseNode child = new ParseNode(newlabel, -1);
+ children.addElement(child);
+ child.setParent(this);
+ return child;
+ }
+
+ public ParseNode addChild (String newlabel, int line) {
+ ParseNode child = new ParseNode(newlabel, line);
+ children.addElement(child);
+ child.setParent(this);
+ return child;
+ }
+
+ public ParseNodeVector getChildren() {
+ return children;
+ }
+
+ public ParseNode getChild (String label) {
+ int i;
+ ParseNode p;
+
+ for (i = 0; i < children.size(); i++) {
+ p = children.elementAt(i);
+ if (p.getLabel().equals(label)) {
+ return p;
+ }
+ }
+
+ return null;
+ }
+
+ public ParseNode getRoot() {
+ return (parent == null) ? this : parent.getRoot();
+ }
+
+ public String getTerminal () {
+ ParseNode pn = children.elementAt(0);
+ if (pn == null) {
+ return null;
+ } else {
+ return pn.getLabel();
+ }
+ }
+
+
+ public ParseNodeVector getChildren(String label) {
+ int i;
+ ParseNodeVector v = new ParseNodeVector();
+
+ for (i = 0; i < children.size(); i++) {
+ ParseNode pn = children.elementAt(i);
+ if (pn.getLabel().equals(label))
+ v.addElement(pn);
+ }
+
+ return v;
+ }
+
+ public String getNodeName() {
+ return label + " - " + getLine();
+ }
+
+ public int getNeighborCount() {
+ return children.size();
+ }
+
+ public Object getNeighbor(int index) {
+ return children.elementAt(index);
+ }
+
+ public String doIndent(int indent) {
+
+ String output = new String();
+ for(int i=0;i<indent;i++) output += " ";
+ return output;
+ }
+
+ public String PPrint(int indent, boolean recursive) {
+
+ String output = new String();
+
+ if (children.size()==0) {
+ output += doIndent(indent) + "<" + label + "/>\n";
+ } else {
+ output += doIndent(indent) + "<" + label + ">\n";
+ indent += 2;
+
+ if (recursive) {
+ for (int i = 0; i < children.size(); i++) {
+ Walkable w = (Walkable)children.elementAt(i);
+ output += w.PPrint(indent, true);
+ }
+ } else {
+ for (int i = 0; i < children.size(); i++) {
+ Walkable w = (Walkable)children.elementAt(i);
+ output += doIndent(indent) + "<" + w.getNodeName() + "/>\n";
+ }
+ }
+
+ indent -= 2;
+ output += doIndent(indent) + "</" + label + ">\n";
+ }
+
+ return output;
+ }
+
+}
+
--- /dev/null
+/*
+
+ Class: ParseNodeDOTVisitor
+ Author: Dan Roy
+ Purpose: Traverses a ParseNode tree and generates a DOT file that represents the parse
+ tree.
+
+*/
+
+package MCC.IR;
+
+import java.util.*;
+
+public class ParseNodeDOTVisitor {
+
+ java.io.PrintWriter output;
+ int tokennumber;
+ int color;
+
+ private ParseNodeDOTVisitor(java.io.OutputStream output) {
+ tokennumber = 0;
+ color = 0;
+ this.output = new java.io.PrintWriter(output, true);
+ }
+
+ private String getNewID(String name) {
+ tokennumber = tokennumber + 1;
+ return new String (name+tokennumber);
+ }
+
+ public static void visit(java.io.OutputStream output, ParseNode root) {
+ ParseNodeDOTVisitor visitor = new ParseNodeDOTVisitor(output);
+ visitor.make(root);
+ }
+
+ private void make(ParseNode root) {
+ output.println("digraph dotvisitor {");
+ output.println("\tsize=\"7, 10\";");
+ traverse(root, getNewID("root"));
+ output.println("}\n");
+ }
+
+ private String newColor() {
+
+
+ if (color == 0) {
+ color++;
+ return new String("red");
+ } else if (color == 1) {
+ color++;
+ return new String("green");
+ } else {
+ color = 0;
+ return new String("blue");
+ }
+ }
+
+ private void traverse(ParseNode node, String nodeid) {
+ output.println("\t" + nodeid + " [label=\"" + node.getLabel() + "\",shape=box];");
+ ParseNodeVector children = node.getChildren();
+ for (int i = 0; i < children.size(); i++) {
+ ParseNode child = children.elementAt(i);
+ String childid = getNewID("node");
+ output.println("\t" + nodeid + " -> " + childid + ";");
+ if (child.getLabel()=="rule") {
+ output.println("\tnode [color=" + newColor() + "];");
+ }
+ traverse(child, childid);
+ }
+ }
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.Vector;
+
+public class ParseNodeVector {
+ private Vector v;
+
+ public ParseNodeVector() {
+ v = new Vector();
+ }
+
+ public void addElement(ParseNode pn) {
+ v.addElement(pn);
+ }
+
+ public void insertElementAt(ParseNode pn, int n) {
+ v.insertElementAt(pn, n);
+ }
+
+ public ParseNode elementAt(int i) {
+ return (ParseNode) v.elementAt(i);
+ }
+
+ public int size() {
+ return v.size();
+ }
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public abstract class Predicate extends LogicStatement {
+ protected Predicate() {}
+}
+
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public interface PrettyPrinter {
+ void output(String s);
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public abstract class Quantifier {
+
+ public abstract Set getRequiredDescriptors();
+
+ public abstract void generate_open(CodeWriter writer);
+}
--- /dev/null
+package MCC.IR;
+
+/**
+ * RelationDescriptor
+ *
+ * represents a set in the model space
+ */
+
+public class RelationDescriptor extends Descriptor {
+
+ SetDescriptor domain;
+ SetDescriptor range;
+ boolean bStatic;
+
+ public RelationDescriptor(String name) {
+ super(name);
+ bStatic = false;
+ domain = null;
+ range = null;
+ }
+
+ public boolean isStatic() {
+ return bStatic;
+ }
+
+ public void isStatic(boolean newvalue) {
+ bStatic = newvalue;
+ }
+
+ public void setDomain(SetDescriptor td) {
+ domain = td;
+ }
+
+ public SetDescriptor getDomain() {
+ return domain;
+ }
+
+ public void setRange(SetDescriptor td) {
+ range = td;
+ }
+
+ public SetDescriptor getRange() {
+ return range;
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class RelationExpr extends Expr {
+
+ // #TBD#: right now i'm not sure if this is the best way to organize the relationexpr... it may be better
+ // to have one class represent each a.B.B'.B'' expression with a VarDescriptor for the a and a vector
+ // for the list of B
+ RelationExpr subdomain;
+ VarDescriptor domain;
+
+ RelationDescriptor relation;
+ boolean inverse;
+
+ public RelationExpr() {
+ this.domain = null;
+ this.subdomain = null;
+ this.relation = null;
+ this.inverse = false;
+ }
+
+ public RelationExpr(RelationExpr subdomain) {
+ this.subdomain = subdomain;
+ this.domain = null;
+ this.relation = null;
+ this.inverse = false;
+ }
+
+ public void setRelation(RelationDescriptor rd, boolean inverse) {
+ this.relation = rd;
+ this.inverse = inverse;
+ }
+
+ public void setDomain(VarDescriptor vd) {
+ this.domain = vd;
+ }
+
+ public Set getRequiredDescriptors() {
+ HashSet v = new HashSet();
+ v.add(relation);
+ if (subdomain != null) {
+ v.addAll(subdomain.getRequiredDescriptors());
+ }
+ return v;
+ }
+
+ public void generate(CodeWriter writer, VarDescriptor dest) {
+ if (domain != null) { /* base case */
+ writer.outputline(relation.getRange().getType().getSafeSymbol() + " " + dest.getSymbol() + " = " + relation.getSafeSymbol() + "_hash.getFirst(" + domain.getSafeSymbol() + ");");
+ } else {
+ VarDescriptor ld = VarDescriptor.makeNew();
+ subdomain.generate(writer, ld);
+ writer.outputline(relation.getRange().getType().getSafeSymbol() + " " + dest.getSymbol() + " = " + relation.getSafeSymbol() + "_hash.getFirst(" + ld.getSafeSymbol() + ");");
+ }
+
+ }
+
+ public void generate_set(CodeWriter writer, VarDescriptor dest) {
+ if (domain != null) { /* base case */
+ writer.outputline("Set " + dest.getSymbol() + " = " + relation.getSafeSymbol() + "_hash.get(" + domain.getSafeSymbol() + ");");
+ } else {
+ VarDescriptor ld = VarDescriptor.makeNew();
+ subdomain.generate(writer, ld);
+ writer.outputline("Set " + dest.getSymbol() + " = " + relation.getSafeSymbol() + "_hash.get(" + domain.getSafeSymbol() + ");");
+ }
+ }
+
+ public void prettyPrint(PrettyPrinter pp) {
+ if (subdomain != null) {
+ subdomain.prettyPrint(pp);
+ } else {
+ pp.output(domain.getSafeSymbol());
+ }
+
+ pp.output(".");
+
+ if (inverse) {
+ pp.output("~");
+ }
+
+ pp.output(relation.getSafeSymbol());
+ }
+
+ public TypeDescriptor typecheck(SemanticAnalyzer sa) {
+ TypeDescriptor type = null;
+
+ if (domain != null) {
+ type = domain.getType();
+ } else {
+ type = subdomain.typecheck(sa);
+ }
+
+ if (type == null) {
+ return null;
+ }
+
+ /* check to make sure that the types of the relation match up */
+ if (inverse) {
+ TypeDescriptor rangetype = relation.getRange().getType();
+
+ if (rangetype != type) {
+ sa.getErrorReporter().report(null, "Type of left side of relation operator '.' is '" + type.getSymbol() +
+ "' but must be the '" + rangetype.getSymbol() +
+ "', the type of the range of the relation '" + relation.getSymbol() + "'");
+ return null;
+ }
+
+ this.td = relation.getDomain().getType();
+ return this.td;
+ } else { /* not inverse */
+ TypeDescriptor domaintype = relation.getDomain().getType();
+
+ if (domaintype != type) {
+ sa.getErrorReporter().report(null, "Type of left side of relation operator '.' is '" + type.getSymbol() +
+ "' but must be the '" + domaintype.getSymbol() +
+ "', the type of the range of the relation '" + relation.getSymbol() + "'");
+ return null;
+ }
+
+ this.td = relation.getRange().getType();
+ return this.td;
+ }
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class RelationInclusion extends Inclusion {
+
+ Expr leftelementexpr, rightelementexpr;
+ RelationDescriptor relation;
+
+ public RelationInclusion(Expr leftelementexpr, Expr rightelementexpr, RelationDescriptor relation) {
+ this.leftelementexpr = leftelementexpr;
+ this.rightelementexpr = rightelementexpr;
+ this.relation = relation;
+ }
+
+ public Set getTargetDescriptors() {
+ HashSet v = new HashSet();
+ v.add(relation);
+ return v;
+ }
+
+ public Set getRequiredDescriptors() {
+ Set v = leftelementexpr.getRequiredDescriptors();
+ v.addAll(rightelementexpr.getRequiredDescriptors());
+ return v;
+ }
+
+ public void generate(CodeWriter writer) {
+ VarDescriptor ld = VarDescriptor.makeNew("leftele");
+ leftelementexpr.generate(writer, ld);
+ VarDescriptor rd = VarDescriptor.makeNew("rightele");
+ rightelementexpr.generate(writer, rd);
+ writer.outputline(relation.getSafeSymbol() + "_hash->add((int)" + ld.getSafeSymbol() + ", (int)" + rd.getSafeSymbol() + ");");
+ //writer.outputline("printf(\"" + relation.getSafeSymbol() + " (add): <%d, %d>\\n\", " + ld.getSafeSymbol() + ", " + rd.getSafeSymbol() + ");");
+ }
+
+ public boolean typecheck(SemanticAnalyzer sa) {
+ TypeDescriptor ld = leftelementexpr.typecheck(sa);
+ TypeDescriptor rd = rightelementexpr.typecheck(sa);
+
+ if (ld == null || rd == null) {
+ return false;
+ }
+
+ boolean ok = true;
+
+ if (ld != relation.getDomain().getType()) {
+ sa.getErrorReporter().report(null, "Type of left element '" + ld.getSymbol() + "' must match domain type '" + relation.getDomain().getType().getSymbol() + "'");
+ ok = false;
+ }
+
+ if (rd != relation.getRange().getType()) {
+ assert rd.getSymbol() != null;
+ assert relation.getRange().getType() != null : relation.getRange().getSymbol();
+ sa.getErrorReporter().report(null, "Type of right element '" + rd.getSymbol() + "' must match range type '" + relation.getRange().getType().getSymbol() + "'");
+ ok = false;
+ }
+
+ return ok;
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class RelationQuantifier extends Quantifier {
+
+ RelationDescriptor relation;
+ VarDescriptor x, y; // y = x.relation
+
+ public RelationQuantifier() {}
+
+ public void setRelation(RelationDescriptor rd) {
+ relation = rd;
+ }
+
+ public void setTuple(VarDescriptor x, VarDescriptor y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public Set getRequiredDescriptors() {
+ HashSet v = new HashSet();
+ v.add(relation);
+ return v;
+ }
+
+ public String toString() {
+ return "relation quantifier <" + x.getSymbol() + "," + y.getSymbol() + "> in " + relation.getSymbol();
+ }
+
+ public void generate_open(CodeWriter writer) {
+ writer.outputline("for (SimpleIterator* " + x.getSafeSymbol() + "_iterator = " + relation.getSafeSymbol() + "_hash->iterator(); " + x.getSafeSymbol() + "_iterator->hasNext(); ) {");
+ writer.indent();
+ writer.outputline(y.getType().getSafeSymbol() + " " + y.getSafeSymbol() + " = (" + y.getType().getSafeSymbol() + ") " + x.getSafeSymbol() + "_iterator->next();");
+ // #ATTN#: key is called second because next() forwards ptr and key does not!
+ writer.outputline(x.getType().getSafeSymbol() + " " + x.getSafeSymbol() + " = (" + x.getType().getSafeSymbol() + ") " + x.getSafeSymbol() + "_iterator->key();");
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+/**
+ * ReservedFieldDescriptor
+ *
+ * represents an unreferencable region of a structure. usually used
+ * for padding structures or for allocating generic memory space
+ */
+
+public class ReservedFieldDescriptor extends FieldDescriptor {
+
+ static int number = 0;
+
+ public ReservedFieldDescriptor() {
+ super("#RESERVED-" + ReservedFieldDescriptor.number++ + "#");
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+/**
+ * ReservedSetDescriptor
+ *
+ * handles reserved sets: int and Token
+ */
+
+public class ReservedSetDescriptor extends SetDescriptor {
+
+ public ReservedSetDescriptor(String name, TypeDescriptor td) {
+ super(name);
+ setType(td);
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+/**
+ * ReservedTypeDescriptor
+ *
+ * handles reserved types: bit, byte, short, int
+ */
+
+public class ReservedTypeDescriptor extends TypeDescriptor {
+
+ IntegerLiteralExpr size;
+
+ public static final ReservedTypeDescriptor BIT = new ReservedTypeDescriptor("bit", 1);
+ public static final ReservedTypeDescriptor BYTE = new ReservedTypeDescriptor("byte", 8);
+ public static final ReservedTypeDescriptor SHORT = new ReservedTypeDescriptor("short", 16);
+ public static final ReservedTypeDescriptor INT = new ReservedTypeDescriptor("int", 32);
+
+ private ReservedTypeDescriptor(String name, int size) {
+ super(name);
+ this.size = new IntegerLiteralExpr(size);
+ }
+
+ public Expr getSizeExpr() {
+ return size;
+ }
+
+ public String getSafeSymbol() {
+ return getSymbol();
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class Rule {
+
+ static int count = 1;
+
+ Vector quantifiers = new Vector();
+ boolean isstatic = false;
+ boolean isdelay = false;
+ Expr guard = null;
+ Inclusion inclusion = null;
+ SymbolTable st = new SymbolTable();
+
+ String label;
+
+ public Rule () {
+ label = new String("rule" + count++);
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public void setStatic(boolean val) {
+ isstatic = val;
+ }
+
+ public void setDelay(boolean val) {
+ isdelay = val;
+ }
+
+ public void addQuantifier(Quantifier q) {
+ quantifiers.addElement(q);
+ }
+
+ public ListIterator quantifiers() {
+ return quantifiers.listIterator();
+ }
+
+ public void setGuardExpr(Expr guard) {
+ this.guard = guard;
+ }
+
+ public Expr getGuardExpr() {
+ return guard;
+ }
+
+ public void setInclusion(Inclusion inclusion) {
+ this.inclusion = inclusion;
+ }
+
+ public Inclusion getInclusion() {
+ return inclusion;
+ }
+
+ public SymbolTable getSymbolTable() {
+ return st;
+ }
+
+ public Set getRequiredDescriptors() {
+
+ HashSet topdescriptors = new HashSet();
+
+ for (int i = 0; i < quantifiers.size(); i++) {
+ Quantifier q = (Quantifier) quantifiers.elementAt(i);
+ topdescriptors.addAll(q.getRequiredDescriptors());
+ }
+
+ assert guard != null;
+ topdescriptors.addAll(guard.getRequiredDescriptors());
+
+ assert inclusion != null;
+ topdescriptors.addAll(inclusion.getRequiredDescriptors());
+
+ return SetDescriptor.expand(topdescriptors);
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class ScheduleEvent {
+
+ Vector preconditions;
+ Vector postconditions;
+
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public interface SemanticAnalyzer {
+
+ IRErrorReporter getErrorReporter();
+
+ SymbolTable getSymbolTable();
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+import java.math.BigInteger;
+import MCC.State;
+
+public class SemanticChecker {
+
+ private static final boolean CREATE_MISSING = true;
+
+ public State state;
+
+ Vector vConstraints;
+ Vector vRules;
+
+ SymbolTableStack sts;
+
+ SymbolTable stSets;
+ SymbolTable stRelations;
+ SymbolTable stTypes;
+ SymbolTable stGlobals;
+
+ StructureTypeDescriptor dCurrentType;
+
+ IRErrorReporter er;
+
+ public SemanticChecker () {
+ dCurrentType = null;
+ stTypes = null;
+ er = null;
+ }
+
+ public boolean check(State state, IRErrorReporter er) {
+
+ this.state = state;
+ State.currentState = state;
+
+ // Don't clear the state!! Do clear the IR-related state
+ this.state.stTypes = null;
+
+ if (er == null) {
+ throw new IRException("IRBuilder.build: Received null ErrorReporter");
+ } else {
+ this.er = er;
+ }
+
+ if (state.ptStructures == null) {
+ throw new IRException("IRBuilder.build: Received null ParseNode");
+ }
+
+ state.vConstraints = new Vector();
+ vConstraints = state.vConstraints;
+
+ state.vRules = new Vector();
+ vRules = state.vRules;
+
+ state.stTypes = new SymbolTable();
+ stTypes = state.stTypes;
+
+ state.stSets = new SymbolTable();
+ stSets = state.stSets;
+
+ state.stRelations = new SymbolTable();
+ stRelations = state.stRelations;
+
+ state.stGlobals = new SymbolTable();
+ stGlobals = state.stGlobals;
+
+ sts = new SymbolTableStack();
+
+ // add int and bool to the types list
+ stTypes.add(ReservedTypeDescriptor.BIT);
+ stTypes.add(ReservedTypeDescriptor.BYTE);
+ stTypes.add(ReservedTypeDescriptor.SHORT);
+ stTypes.add(ReservedTypeDescriptor.INT);
+
+ stSets.add(new ReservedSetDescriptor("int", ReservedTypeDescriptor.INT));
+ stSets.add(new ReservedSetDescriptor("token", ReservedTypeDescriptor.INT));
+
+ boolean ok = true;
+
+ er.setFilename(state.infile + ".struct");
+ if (!parse_structures(state.ptStructures)) {
+ ok = false;
+ }
+
+ er.setFilename(state.infile + ".space");
+ if (!parse_space(state.ptSpace)) {
+ ok = false;
+ }
+
+ er.setFilename(state.infile + ".constraints");
+ if (!parse_constraints(state.ptConstraints)) {
+ ok = false;
+ }
+
+ er.setFilename(state.infile + ".model");
+ if (!parse_rules(state.ptModel)) {
+ ok = false;
+ }
+
+ return ok;
+ }
+
+ /********************** HELPER FUNCTIONS ************************/
+
+ /**
+ * special case lookup that returns null if no such type exists
+ */
+ private TypeDescriptor lookupType(String typename) {
+ return lookupType(typename, false);
+ }
+
+ /**
+ * does a look up in the types symbol table. if the type is
+ * not found than a missing type descriptor is returned
+ */
+ private TypeDescriptor lookupType(String typename, boolean createmissing) {
+ if (stTypes.get(typename) != null) {
+ // the type exists, so plug in the descriptor directly
+ return (TypeDescriptor) stTypes.get(typename);
+ } else if (createmissing) {
+ return new MissingTypeDescriptor(typename);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * reserve a name
+ */
+ private VarDescriptor reserveName(ParseNode pn) {
+ assert pn != null;
+ String varname = pn.getTerminal();
+ assert varname != null;
+
+ /* do semantic check and if valid, add it to symbol table
+ and add it to the quantifier as well */
+ if (sts.peek().contains(varname)) {
+ /* Semantic Error: redefinition */
+ er.report(pn, "Redefinition of '" + varname + "'");
+ return null;
+ } else {
+ VarDescriptor vd = new VarDescriptor(varname);
+ sts.peek().add(vd);
+ return vd;
+ }
+ }
+
+ /**
+ * special case lookup that returns null if no such set exists
+ */
+ private SetDescriptor lookupSet(String setname) {
+ return lookupSet(setname, false);
+ }
+
+ /**
+ * does a look up in the set's symbol table. if the set is
+ * not found than a missing set descriptor is returned
+ */
+ private SetDescriptor lookupSet(String setname, boolean createmissing) {
+ if (stSets.get(setname) != null) {
+ // the set exists, so plug in the descriptor directly
+ return (SetDescriptor) stSets.get(setname);
+ } else if (createmissing) {
+ return new MissingSetDescriptor(setname);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * does a look up in the set's symbol table. if the set is
+ * not found than a missing set descriptor is returned
+ */
+ private RelationDescriptor lookupRelation(String relname) {
+ if (stRelations.get(relname) != null) {
+ // the relation exists, so plug in the descriptor directly
+ return (RelationDescriptor) stRelations.get(relname);
+ } else {
+ return null;
+ }
+ }
+
+
+ private static int count = 0;
+ private boolean precheck(ParseNode pn, String label) {
+ if (pn == null) {
+ er.report(pn, "IE: Expected '" + label + "', got null");
+ assert false;
+ return false;
+ }
+
+ if (! pn.getLabel().equals(label)) {
+ er.report(pn, "IE: Expected '" + label + "', got '" + pn.getLabel() + "'");
+ assert false;
+ return false;
+ }
+
+ if (state.verbose >= 2) {
+ System.err.println("visiting*" + (count++) + ": " + label);
+ }
+
+ return true;
+ }
+
+ /********************* PARSING FUNCTIONS ************************/
+
+ private boolean parse_rules(ParseNode pn) {
+ if (!precheck(pn, "rules")) {
+ return false;
+ }
+
+ boolean ok = true;
+ ParseNodeVector rules = pn.getChildren();
+
+ for (int i = 0; i < rules.size(); i++) {
+ ParseNode rule = rules.elementAt(i);
+ if (!parse_rule(rule)) {
+ ok = false;
+ }
+ }
+
+ /* type check */
+ Iterator ruleiterator = state.vRules.iterator();
+
+ while (ruleiterator.hasNext()) {
+ Rule rule = (Rule) ruleiterator.next();
+ Expr guard = rule.getGuardExpr();
+ final SymbolTable rulest = rule.getSymbolTable();
+ SemanticAnalyzer sa = new SemanticAnalyzer() {
+ public IRErrorReporter getErrorReporter() { return er; }
+ public SymbolTable getSymbolTable() { return rulest; }
+ };
+ TypeDescriptor guardtype = guard.typecheck(sa);
+
+ if (guardtype == null) {
+ ok = false;
+ } else if (guardtype != ReservedTypeDescriptor.INT) {
+ er.report(null, "Type of guard must be 'int' not '" + guardtype.getSymbol() + "'");
+ ok = false;
+ }
+
+ if (!rule.getInclusion().typecheck(sa)) {
+ ok = false;
+ }
+
+ Iterator quantifiers = rule.quantifiers();
+
+ while (quantifiers.hasNext()) {
+ Quantifier q = (Quantifier) quantifiers.next();
+
+ if (q instanceof ForQuantifier && !((ForQuantifier)q).typecheck(sa)) {
+ ok = false;
+ }
+ }
+ }
+
+ /* do any post checks ?? */
+
+ return ok;
+ }
+
+ private boolean parse_rule(ParseNode pn) {
+ if (!precheck(pn, "rule")) {
+ return false;
+ }
+
+ boolean ok = true;
+ Rule rule = new Rule();
+
+ /* get rule type */
+ boolean isstatic = pn.getChild("static") != null;
+ boolean isdelay = pn.getChild("delay") != null;
+ rule.setStatic(isstatic);
+ rule.setDelay(isdelay);
+
+ /* set up symbol table for constraint */
+ assert sts.empty();
+ sts.push(stGlobals);
+ sts.push(rule.getSymbolTable());
+
+ /* optional quantifiers */
+ if (pn.getChild("quantifiers") != null) {
+ ParseNodeVector quantifiers = pn.getChild("quantifiers").getChildren();
+
+ for (int i = 0; i < quantifiers.size(); i++) {
+ ParseNode qn = quantifiers.elementAt(i);
+ Quantifier quantifier = parse_quantifier(qn);
+
+ if (quantifier == null) {
+ ok = false;
+ } else {
+ rule.addQuantifier(quantifier);
+ }
+ }
+ }
+
+ /* get guard expr */
+ Expr guard = parse_expr(pn.getChild("expr"));
+
+ if (guard == null) {
+ ok = false;
+ } else {
+ rule.setGuardExpr(guard);
+ }
+
+ /* inclusion constraint */
+ Inclusion inclusion = parse_inclusion(pn.getChild("inclusion"));
+
+ if (inclusion == null) {
+ ok = false;
+ } else {
+ rule.setInclusion(inclusion);
+ }
+
+ /* pop symbol table stack */
+ SymbolTable st = sts.pop();
+ sts.pop(); /* pop off globals */
+
+ /* make sure the stack we pop is our rule s.t. */
+ assert st == rule.getSymbolTable();
+ assert sts.empty();
+
+ /* add rule to global set */
+ vRules.addElement(rule);
+
+ return ok;
+ }
+
+ private Inclusion parse_inclusion(ParseNode pn) {
+ if (!precheck(pn, "inclusion")) {
+ return null;
+ }
+
+ if (pn.getChild("set") != null) {
+ ParseNode set = pn.getChild("set");
+ Expr expr = parse_expr(set.getChild("expr"));
+
+ if (expr == null) {
+ return null;
+ }
+
+ String setname = set.getChild("name").getTerminal();
+ assert setname != null;
+ SetDescriptor sd = lookupSet(setname);
+
+ if (sd == null) {
+ er.report(set.getChild("name"), "Undefined set '" + setname + "'");
+ return null;
+ }
+
+ return new SetInclusion(expr, sd);
+ } else if (pn.getChild("relation") != null) {
+ ParseNode relation = pn.getChild("relation");
+ Expr leftexpr = parse_expr(relation.getChild("left").getChild("expr"));
+ Expr rightexpr = parse_expr(relation.getChild("right").getChild("expr"));
+
+ if ((leftexpr == null) || (rightexpr == null)) {
+ return null;
+ }
+
+ String relname = relation.getChild("name").getTerminal();
+ assert relname != null;
+ RelationDescriptor rd = lookupRelation(relname);
+
+ if (rd == null) {
+ er.report(relation.getChild("name"), "Undefined relation '" + relname + "'");
+ return null;
+ }
+
+ return new RelationInclusion(leftexpr, rightexpr, rd);
+ } else {
+ throw new IRException();
+ }
+ }
+
+ private boolean parse_constraints(ParseNode pn) {
+ if (!precheck(pn, "constraints")) {
+ return false;
+ }
+
+ boolean ok = true;
+ ParseNodeVector constraints = pn.getChildren();
+
+ for (int i = 0; i < constraints.size(); i++) {
+ ParseNode constraint = constraints.elementAt(i);
+ assert constraint.getLabel().equals("constraint");
+ if (!parse_constraint(constraint)) {
+ ok = false;
+ }
+ }
+
+ /* do any post checks... (type constraints, etc?) */
+
+ return ok;
+ }
+
+ private boolean parse_constraint(ParseNode pn) {
+ if (!precheck(pn, "constraint")) {
+ return false;
+ }
+
+ boolean ok = true;
+ Constraint constraint = new Constraint();
+
+ /* test crash */
+ boolean crash = pn.getChild("crash") != null;
+ constraint.setCrash(crash);
+
+ /* set up symbol table for constraint */
+ assert sts.empty();
+ sts.push(constraint.getSymbolTable());
+
+ /* get quantifiers */
+ if (pn.getChild("quantifiers") != null) {
+ ParseNodeVector quantifiers = pn.getChild("quantifiers").getChildren();
+
+ for (int i = 0; i < quantifiers.size(); i++) {
+ ParseNode qn = quantifiers.elementAt(i);
+ assert qn.getLabel().equals("quantifier");
+ Quantifier quantifier = parse_quantifier(qn);
+ if (quantifier == null) {
+ ok = false;
+ } else {
+ constraint.addQuantifier(quantifier);
+ }
+ }
+ }
+
+ /* get body */
+ LogicStatement logicexpr = parse_body(pn.getChild("body"));
+
+ if (logicexpr == null) {
+ ok = false;
+ } else {
+ constraint.setLogicStatement(logicexpr);
+ }
+
+ /* pop symbol table stack */
+ SymbolTable st = sts.pop();
+
+ /* make sure the stack we pop is our constraint s.t. */
+ assert st == constraint.getSymbolTable();
+ assert sts.empty();
+
+ /* add to vConstraints */
+ vConstraints.addElement(constraint);
+
+ return ok;
+ }
+
+ private Quantifier parse_quantifier(ParseNode pn) {
+ if (!precheck(pn, "quantifier")) {
+ return null;
+ }
+
+ if (pn.getChild("forall") != null) { /* forall element in Set */
+ SetQuantifier sq = new SetQuantifier();
+
+ /* get var */
+ VarDescriptor vd = reserveName(pn.getChild("var"));
+
+ if (vd == null) {
+ return null;
+ }
+
+ sq.setVar(vd);
+
+ /* parse the set */
+ SetDescriptor set = parse_set(pn.getChild("set"));
+ assert set != null;
+ sq.setSet(set);
+
+ vd.setType(set.getType());
+
+ /* return to caller */
+ return sq;
+
+ } else if (pn.getChild("relatiion") != null) { /* for < v1, v2 > in Relation */
+ RelationQuantifier rq = new RelationQuantifier();
+
+ /* get vars */
+ VarDescriptor vd1 = reserveName(pn.getChild("left"));
+ VarDescriptor vd2 = reserveName(pn.getChild("right"));
+
+ if ((vd1 == null) || (vd2 == null)) {
+ return null;
+ }
+
+ rq.setTuple(vd1, vd2);
+
+ /* get relation */
+ String relationname = pn.getChild("relation").getTerminal();
+ assert relationname != null;
+ RelationDescriptor rd = lookupRelation(relationname);
+
+ if (rd == null) {
+ return null;
+ }
+
+ rq.setRelation(rd);
+ vd1.setType(rd.getDomain().getType());
+ vd2.setType(rd.getRange().getType());
+ return rq;
+ } else if (pn.getChild("for") != null) { /* for j = x to y */
+ ForQuantifier fq = new ForQuantifier();
+
+ /* grab var */
+ VarDescriptor vd = reserveName(pn.getChild("var"));
+
+ if (vd == null) {
+ return null;
+ }
+
+ vd.setType(ReservedTypeDescriptor.INT);
+ fq.setVar(vd);
+
+ /* grab lower/upper bounds */
+ Expr lower = parse_expr(pn.getChild("lower").getChild("expr"));
+ Expr upper = parse_expr(pn.getChild("upper").getChild("expr"));
+
+ if ((lower == null) || (upper == null)) {
+ return null;
+ }
+
+ fq.setBounds(lower, upper);
+
+ return fq;
+ } else {
+ throw new IRException("not supported yet");
+ }
+
+ }
+
+ private LogicStatement parse_body(ParseNode pn) {
+ if (!precheck(pn, "body")) {
+ return null;
+ }
+
+ if (pn.getChild("and") != null) {
+ /* body AND body */
+ LogicStatement left, right;
+ left = parse_body(pn.getChild("and").getChild("left").getChild("body"));
+ right = parse_body(pn.getChild("and").getChild("right").getChild("body"));
+
+ if ((left == null) || (right == null)) {
+ return null;
+ }
+
+ // what do we want to call the and/or/not body classes?
+ return new LogicStatement(LogicStatement.AND, left, right);
+ } else if (pn.getChild("or") != null) {
+ /* body OR body */
+ LogicStatement left, right;
+ left = parse_body(pn.getChild("or").getChild("left").getChild("body"));
+ right = parse_body(pn.getChild("or").getChild("right").getChild("body"));
+
+ if ((left == null) || (right == null)) {
+ return null;
+ }
+
+ return new LogicStatement(LogicStatement.OR, left, right);
+ } else if (pn.getChild("not") != null) {
+ /* NOT body */
+ LogicStatement left = parse_body(pn.getChild("not").getChild("left").getChild("body"));
+
+ if (left == null) {
+ return null;
+ }
+
+ return new LogicStatement(LogicStatement.NOT, left);
+ } else if (pn.getChild("predicate") != null) {
+ return parse_predicate(pn.getChild("predicate"));
+ } else {
+ throw new IRException();
+ }
+ }
+
+ private Predicate parse_predicate(ParseNode pn) {
+ if (!precheck(pn, "predicate")) {
+ return null;
+ }
+
+ if (pn.getChild("comparison") != null) {
+ ParseNode cn = pn.getChild("comparison");
+
+ /* get the expr's */
+ Expr left = parse_expr(cn.getChild("left").getChild("expr"));
+ Expr right = parse_expr(cn.getChild("right").getChild("expr"));
+
+ if ((left == null) || (right == null)) {
+ return null;
+ }
+
+ /* get comparison operator */
+ String comparison = cn.getChild("compare").getTerminal();
+ assert comparison != null;
+
+ return new ComparisonPredicate(comparison, left, right);
+ } else if (pn.getChild("inclusion") != null) {
+ ParseNode in = pn.getChild("inclusion");
+
+ /* get quantiifer var */
+ VarDescriptor vd = parse_quantifiervar(in.getChild("quantifiervar"));
+
+ if (vd == null) {
+ return null;
+ }
+
+ /* get set expr */
+ SetExpr setexpr = parse_setexpr(in.getChild("setexpr"));
+
+ if (setexpr == null) {
+ return null;
+ }
+
+ return new InclusionPredicate(vd, setexpr);
+ } else {
+ throw new IRException();
+ }
+ }
+
+ private SetDescriptor parse_set(ParseNode pn) {
+ if (!precheck(pn, "set")) {
+ return null;
+ }
+
+ if (pn.getChild("name") != null) {
+ String setname = pn.getChild("name").getTerminal();
+ assert setname != null;
+
+ if (!stSets.contains(setname)) {
+ /* Semantic Error: unknown set */
+ er.report(pn, "Unknown set '" + setname + "' referenced in quantifier");
+ return null;
+ } else {
+ /* all good, get setdescriptor */
+ SetDescriptor sd = (SetDescriptor) stSets.get(setname);
+ assert sd != null;
+ return sd;
+ }
+ } else if (pn.getChild("listofliterals") != null) {
+ TokenSetDescriptor tokenset = new TokenSetDescriptor();
+ ParseNodeVector token_literals = pn.getChild("listofliterals").getChildren();
+ assert token_literals.size() > 0;
+
+ for (int i = 0; i < token_literals.size(); i++) {
+ ParseNode literal = token_literals.elementAt(i);
+ assert literal.getLabel().equals("literal");
+ LiteralExpr litexpr = parse_literal(literal);
+
+ if (litexpr == null) {
+ return null;
+ }
+
+ if (litexpr instanceof TokenLiteralExpr || litexpr instanceof IntegerLiteralExpr) {
+ tokenset.addLiteral(litexpr);
+ } else {
+ er.report(literal, "Elements of a user-defined set must be of type token or integer");
+ // return null; /* don't think we need to return null */
+ }
+ }
+
+ return tokenset;
+ } else {
+ throw new IRException(pn.getTerminal());
+ }
+ }
+
+ private boolean parse_space(ParseNode pn) {
+ if (!precheck(pn, "space")) {
+ return false;
+ }
+
+ boolean ok = true;
+ ParseNodeVector sets = pn.getChildren("setdefinition");
+ ParseNodeVector relations = pn.getChildren("relationdefinition");
+
+ assert pn.getChildren().size() == (sets.size() + relations.size());
+
+ /* parse sets */
+ for (int i = 0; i < sets.size(); i++) {
+ if (!parse_setdefinition(sets.elementAt(i))) {
+ ok = false;
+ }
+ }
+
+ /* parse relations */
+ for (int i = 0; i < relations.size(); i++) {
+ if (!parse_relationdefinition(relations.elementAt(i))) {
+ ok = false;
+ }
+ }
+
+ // ok, all the spaces have been parsed, now we should typecheck and check
+ // for cycles etc.
+
+ // #TBD#: typecheck and check for cycles
+
+ /* replace missing with actual */
+ Iterator allsets = state.stSets.descriptors();
+
+ while (allsets.hasNext()) {
+ SetDescriptor sd = (SetDescriptor) allsets.next();
+ Vector subsets = sd.getSubsets();
+
+ for (int i = 0; i < subsets.size(); i++) {
+ SetDescriptor subset = (SetDescriptor) subsets.elementAt(i);
+
+ if (subset instanceof MissingSetDescriptor) {
+ SetDescriptor newsubset = lookupSet(subset.getSymbol());
+
+ if (newsubset == null) {
+ er.report(null, "Unknown subset '" + subset.getSymbol() + "'");
+ } else {
+ subsets.setElementAt(newsubset, i);
+ }
+ }
+ }
+ }
+
+ return ok;
+ }
+
+ private boolean parse_setdefinition(ParseNode pn) {
+ if (!precheck(pn, "setdefinition")) {
+ return false;
+ }
+
+ boolean ok = true;
+
+ /* get set name */
+ String setname = pn.getChild("name").getTerminal();
+ assert (setname != null);
+
+ SetDescriptor sd = new SetDescriptor(setname);
+
+ /* get set type */
+ String settype = pn.getChild("type").getTerminal();
+ TypeDescriptor type = lookupType(settype);
+ if (type == null) {
+ er.report(pn, "Undefined type '" + settype + "'");
+ ok = false;
+ } else {
+ sd.setType(type);
+ }
+
+ /* is this a partition? */
+ boolean partition = pn.getChild("partition") != null;
+ sd.isPartition(partition);
+
+ /* if set has subsets, add them to set descriptor */
+ if (pn.getChild("setlist") != null) {
+ ParseNodeVector setlist = pn.getChild("setlist").getChildren();
+
+ for (int i = 0; i < setlist.size(); i++) {
+ String subsetname = setlist.elementAt(i).getLabel();
+ sd.addSubset(lookupSet(subsetname, CREATE_MISSING));
+ }
+ }
+
+ /* add set to symbol table */
+ if (stSets.contains(setname)) {
+ // Semantic Check: redefinition
+ er.report(pn, "Redefinition of set: " + setname);
+ ok = false;
+ } else {
+ stSets.add(sd);
+ }
+
+ return ok;
+ }
+
+ private boolean parse_relationdefinition(ParseNode pn) {
+ if (!precheck(pn, "relationdefinition")) {
+ return false;
+ }
+
+ boolean ok = true;
+
+ /* get relation name */
+ String relname = pn.getChild("name").getTerminal();
+ assert relname != null;
+
+ RelationDescriptor rd = new RelationDescriptor(relname);
+
+ /* check if static */
+ boolean bStatic = pn.getChild("static") != null;
+ rd.isStatic(bStatic);
+
+ /* get domain */
+ String domainsetname = pn.getChild("domain").getChild("type").getTerminal();
+ assert domainsetname != null;
+
+ /* get range */
+ String rangesetname = pn.getChild("range").getChild("type").getTerminal();
+ assert rangesetname != null;
+
+ /* get domain multiplicity */
+ String domainmult = pn.getChild("domain").getChild("mult").getTerminal();
+ assert domainmult != null;
+
+ /* get range multiplicity */
+ String rangemult = pn.getChild("range").getChild("mult").getTerminal();
+ assert rangemult != null;
+
+ /* NOTE: it is assumed that the sets have been parsed already so that the
+ set namespace is fully populated. any missing setdescriptors for the set
+ symbol table will be assumed to be errors and reported. */
+
+ SetDescriptor domainset = lookupSet(domainsetname);
+ if (domainset == null) {
+ er.report(pn, "Undefined set '" + domainsetname + "' referenced in relation '" + relname + "'");
+ ok = false;
+ } else {
+ rd.setDomain(domainset);
+ }
+
+ SetDescriptor rangeset = lookupSet(rangesetname);
+ if (rangeset == null) {
+ er.report(pn, "Undefined set '" + rangesetname + "' referenced in relation '" + relname + "'");
+ ok = false;
+ } else {
+ rd.setRange(rangeset);
+ }
+
+ // #TBD#: eventually we'll use the multiplicities but now we don't... oh well
+
+ /* lets add the relation to the global symbol table */
+ if (!stRelations.contains(relname)) {
+ stRelations.add(rd);
+ } else {
+ er.report(pn, "Redefinition of relation '" + relname + "'");
+ ok = false;
+ }
+
+ return ok;
+ }
+
+ private boolean parse_structures(ParseNode pn) {
+ if (!precheck(pn, "structures")) {
+ return false;
+ }
+
+ boolean ok = true;
+ ParseNodeVector structures = pn.getChildren("structure");
+
+ for (int i = 0; i < structures.size(); i++) {
+ if (!parse_structure(structures.elementAt(i))) {
+ ok = false;
+ }
+ }
+
+ ParseNodeVector globals = pn.getChildren("global");
+
+ for (int i = 0; i < globals.size(); i++) {
+ if (!parse_global(globals.elementAt(i))) {
+ ok = false;
+ }
+ }
+
+ // ok, all the structures have been parsed, now we gotta type check
+
+ Enumeration types = stTypes.getDescriptors();
+ while (types.hasMoreElements()) {
+ TypeDescriptor t = (TypeDescriptor) types.nextElement();
+
+ if (t instanceof ReservedTypeDescriptor) {
+ // we don't need to check reserved types
+ } else if (t instanceof StructureTypeDescriptor) {
+
+ StructureTypeDescriptor type = (StructureTypeDescriptor) t;
+ TypeDescriptor subtype = type.getSubType();
+
+ // check that the subtype is valid
+ if (subtype instanceof MissingTypeDescriptor) {
+ TypeDescriptor newtype = lookupType(subtype.getSymbol());
+ if (newtype == null) {
+ // subtype not defined anywheere
+ // #TBD#: somehow determine how we can get the original parsenode (global function?)
+ er.report(null, "Undefined subtype '" + subtype.getSymbol() + "'");
+ ok = false;
+ } else {
+ type.setSubType(newtype);
+ }
+ }
+
+ Iterator fields = type.getFields();
+
+ while (fields.hasNext()) {
+ FieldDescriptor field = (FieldDescriptor) fields.next();
+ TypeDescriptor fieldtype = field.getType();
+
+ assert fieldtype != null;
+
+ // check that the type is valid
+ if (fieldtype instanceof MissingTypeDescriptor) {
+ TypeDescriptor newtype = lookupType(fieldtype.getSymbol());
+ if (newtype == null) {
+ // type never defined
+ // #TBD#: replace new ParseNode with original parsenode
+ er.report(null, "Undefined type '" + fieldtype.getSymbol() + "'");
+ ok = false;
+ } else {
+ assert newtype != null;
+ field.setType(newtype);
+ }
+ }
+ }
+
+ Iterator labels = type.getLabels();
+
+ while (labels.hasNext()) {
+ LabelDescriptor label = (LabelDescriptor) labels.next();
+ TypeDescriptor labeltype = label.getType();
+
+ assert labeltype != null;
+
+ // check that the type is valid
+ if (labeltype instanceof MissingTypeDescriptor) {
+ TypeDescriptor newtype = lookupType(labeltype.getSymbol());
+ if (newtype == null) {
+ // type never defined
+ // #TBD#: replace new ParseNode with original parsenode
+ er.report(null, "Undefined type '" + labeltype.getSymbol() + "'");
+ ok = false;
+ } else {
+ assert newtype != null;
+ label.setType(newtype);
+ }
+ }
+ }
+
+ } else {
+ throw new IRException("shouldn't be any other typedescriptor classes");
+ }
+ }
+
+ if (!ok) {
+ return false;
+ }
+
+ types = stTypes.getDescriptors();
+
+ while (types.hasMoreElements()) {
+ TypeDescriptor t = (TypeDescriptor) types.nextElement();
+
+ if (t instanceof ReservedTypeDescriptor) {
+ // we don't need to check reserved types
+ } else if (t instanceof StructureTypeDescriptor) {
+
+ StructureTypeDescriptor type = (StructureTypeDescriptor)t;
+ TypeDescriptor subtype = type.getSubType();
+ Iterator fields = type.getFields();
+
+ while (fields.hasNext()) {
+ FieldDescriptor field = (FieldDescriptor) fields.next();
+
+ if (field instanceof ArrayDescriptor) {
+ ArrayDescriptor ad = (ArrayDescriptor) field;
+ Expr indexbound = ad.getIndexBound();
+ TypeDescriptor indextype = indexbound.typecheck(new SemanticAnalyzer() {
+ public IRErrorReporter getErrorReporter() { return er; }
+ public SymbolTable getSymbolTable() { return stGlobals; }
+ });
+
+ if (indextype == null) {
+ ok = false;
+ } else if (indextype != ReservedTypeDescriptor.INT) {
+ er.report(null, "'" + type.getSymbol() + "." + field.getSymbol() + "' index bounds must be type 'int' not '" + indextype.getSymbol() + "'");
+ ok = false;
+ }
+ }
+ }
+
+ Iterator labels = type.getLabels();
+
+ while (labels.hasNext()) {
+ LabelDescriptor label = (LabelDescriptor) labels.next();
+ Expr index = label.getIndex();
+
+ if (index != null) {
+ TypeDescriptor indextype = index.typecheck(new SemanticAnalyzer() {
+ public IRErrorReporter getErrorReporter() { return er; }
+ public SymbolTable getSymbolTable() { return stGlobals; }
+ });
+
+ if (indextype != ReservedTypeDescriptor.INT) {
+ er.report(null, "Label '" + type.getSymbol() + "." + label.getSymbol() + "' index must be type 'int' not '" + indextype.getSymbol() + "'");
+ ok = false;
+ }
+ }
+ }
+
+ } else {
+ throw new IRException("shouldn't be any other typedescriptor classes");
+ }
+
+ }
+
+ // #TBD#: need to make sure that no cycles exist in any of the declarations or subtypes
+ // subtypes, of course, are not real subtypes, they are merely a way to validate a
+ // cast, i believe
+
+ return ok;
+ }
+
+ private boolean parse_global(ParseNode pn) {
+ if (!precheck(pn, "global")) {
+ return false;
+ }
+
+ String name = pn.getChild("name").getTerminal();
+ assert name != null;
+
+ String type = pn.getChild("type").getTerminal();
+ assert type != null;
+ TypeDescriptor td = lookupType(type);
+ assert td != null;
+ assert !(td instanceof ReservedTypeDescriptor);
+
+ if (stGlobals.contains(name)) {
+ /* redefinition of global */
+ er.report(pn, "Redefinition of global '" + name + "'");
+ return false;
+ }
+
+ stGlobals.add(new VarDescriptor(name, name, td));
+ return true;
+ }
+
+ private boolean parse_structure(ParseNode pn) {
+ if (!precheck(pn, "structure")) {
+ return false;
+ }
+
+ boolean ok = true;
+ String typename = pn.getChild("name").getTerminal();
+ StructureTypeDescriptor type = new StructureTypeDescriptor(typename);
+
+ if (pn.getChild("subtype") != null) {
+ // has a subtype, lets try to resolve it
+ String subtype = pn.getChild("subtype").getTerminal();
+
+ if (subtype.equals(typename)) {
+ // Semantic Error: cyclic inheritance
+ er.report(pn, "Cyclic inheritance prohibited");
+ ok = false;
+ }
+
+ /* lookup the type to get the type descriptor */
+ type.setSubType(lookupType(subtype, CREATE_MISSING));
+ }
+
+ // set the current type so that the recursive parses on the labels
+ // and fields can add themselves automatically to the current type
+ dCurrentType = type;
+
+ // parse the labels and fields
+ if (!parse_labelsandfields(pn.getChild("lf"))) {
+ ok = false;
+ }
+
+ if (stTypes.contains(typename)) {
+ er.report(pn, "Redefinition of type '" + typename + "'");
+ ok = false;
+ } else {
+ stTypes.add(type);
+ }
+
+ return ok;
+ }
+
+ private boolean parse_labelsandfields(ParseNode pn) {
+ if (!precheck(pn, "lf")) {
+ return false;
+ }
+
+ boolean ok = true;
+
+ // check the fields first (need the field names
+ // to type check the labels)
+ if (!parse_fields(pn.getChild("fields"))) {
+ ok = false;
+ }
+
+ // check the labels now that all the fields are sorted
+ if (!parse_labels(pn.getChild("labels"))) {
+ ok = false;
+ }
+
+ return ok;
+ }
+
+ private boolean parse_fields(ParseNode pn) {
+ if (!precheck(pn, "fields")) {
+ return false;
+ }
+
+ boolean ok = true;
+
+ /* NOTE: because the order of the fields is important when defining a data structure,
+ and because the order is defined by the order of the fields defined in the field
+ vector, its important that the parser returns the fields in the correct order */
+
+ ParseNodeVector fields = pn.getChildren();
+
+ for (int i = 0; i < fields.size(); i++) {
+ ParseNode field = fields.elementAt(i);
+ FieldDescriptor fd;
+ boolean reserved;
+ String name = null;
+
+ if (field.getChild("reserved") != null) {
+ // reserved field
+ // #TBD#: it will be necessary for reserved field descriptors to generate
+ // a unique symbol for the type descriptor requires it for its hashtable
+ fd = new ReservedFieldDescriptor();
+ reserved = true;
+ } else {
+ name = field.getChild("name").getTerminal();
+ fd = new FieldDescriptor(name);
+ reserved = false;
+ }
+
+ String type = field.getChild("type").getTerminal();
+ boolean ptr = field.getChild("*") != null;
+ fd.setPtr(ptr);
+
+ fd.setType(lookupType(type, CREATE_MISSING));
+
+ if (field.getChild("index") != null) {
+ // field is an array, so create an array descriptor to wrap the
+ // field descriptor and then replace the top level field descriptor with
+ // this array descriptor
+ Expr expr = parse_expr(field.getChild("index").getChild("expr"));
+ if (expr == null) {
+ // #ATTN#: do we really want to return an exception here?
+ throw new IRException("invalid index expression");
+ }
+ ArrayDescriptor ad = new ArrayDescriptor(fd, expr);
+ fd = ad;
+ }
+
+ // add the current field to the current type
+ if (reserved == false) {
+ // lets double check that we are redefining a field
+ if (dCurrentType.getField(name) != null) {
+ // Semantic Error: field redefinition
+ er.report(pn, "Redefinition of field '" + name + "'");
+ ok = false;
+ } else {
+ dCurrentType.addField(fd);
+ }
+ } else {
+ dCurrentType.addField(fd);
+ }
+ }
+
+ return ok;
+ }
+
+ private boolean parse_labels(ParseNode pn) {
+ if (!precheck(pn, "labels")) {
+ return false;
+ }
+
+ boolean ok = true;
+
+ /* NOTE: parse_labels should be called after the fields have been parsed because any
+ labels not found in the field set of the current type will be flagged as errors */
+
+ ParseNodeVector labels = pn.getChildren();
+
+ for (int i = 0; i < labels.size(); i++) {
+ ParseNode label = labels.elementAt(i);
+ String name = label.getChild("name").getTerminal();
+ LabelDescriptor ld = new LabelDescriptor(name);
+
+ if (label.getChild("index") != null) {
+ Expr expr = parse_expr(label.getChild("index").getChild("expr"));
+ if (expr == null) {
+ /* #ATTN#: do we really want to return an exception here? */
+ throw new IRException("Invalid expression");
+ }
+ ld.setIndex(expr);
+ }
+
+ String type = label.getChild("type").getTerminal();
+
+ ld.setType(lookupType(type, CREATE_MISSING));
+
+ String field = label.getChild("field").getTerminal();
+ FieldDescriptor fd = dCurrentType.getField(field);
+
+ if (fd == null) {
+ /* Semantic Error: Undefined field in label */
+ er.report(label, "Undefined field '" + field + "' in label");
+ ok = false;
+ } else {
+ ld.setField(fd);
+ }
+
+ /* add label to current type */
+ if (dCurrentType.getLabel(name) != null) {
+ /* semantic error: label redefinition */
+ er.report(pn, "Redefinition of label '" + name + "'");
+ ok = false;
+ } else {
+ dCurrentType.addLabel(ld);
+ }
+ }
+
+ return ok;
+ }
+
+ private Expr parse_expr(ParseNode pn) {
+ if (!precheck(pn, "expr")) {
+ return null;
+ }
+
+ if (pn.getChild("var") != null) {
+ // we've got a variable reference... we'll have to scope check it later
+ // when we are completely done... there are also some issues of cyclic definitions
+ return new VarExpr(pn.getChild("var").getTerminal());
+ } else if (pn.getChild("literal") != null) {
+ return parse_literal(pn.getChild("literal"));
+ } else if (pn.getChild("operator") != null) {
+ return parse_operator(pn.getChild("operator"));
+ } else if (pn.getChild("relation") != null) {
+ return parse_relation(pn.getChild("relation"));
+ } else if (pn.getChild("sizeof") != null) {
+ return parse_sizeof(pn.getChild("sizeof"));
+ } else if (pn.getChild("simple_expr") != null) {
+ return parse_simple_expr(pn.getChild("simple_expr"));
+ } else if (pn.getChild("elementof") != null) {
+ return parse_elementof(pn.getChild("elementof"));
+ } else if (pn.getChild("tupleof") != null) {
+ return parse_tupleof(pn.getChild("tupleof"));
+ } else if (pn.getChild("isvalid") != null) {
+ er.report(pn, "Operation 'isvalid' is currently unsupported.");
+ return null;
+ } else {
+ er.report(pn, "Unknown or invalid expression type '" + pn.getTerminal() + "'");
+ return null;
+ }
+ }
+
+ private Expr parse_elementof(ParseNode pn) {
+ if (!precheck(pn, "elementof")) {
+ return null;
+ }
+
+ /* get setname */
+ String setname = pn.getChild("name").getTerminal();
+ assert setname != null;
+ SetDescriptor sd = lookupSet(setname);
+
+ if (sd == null) {
+ er.report(pn, "Undefined set '" + setname + "'");
+ return null;
+ }
+
+ /* get left side expr */
+ Expr expr = parse_expr(pn.getChild("expr"));
+
+ if (expr == null) {
+ return null;
+ }
+
+ return new ElementOfExpr(expr, sd);
+ }
+
+ private Expr parse_tupleof(ParseNode pn) {
+ if (!precheck(pn, "tupleof")) {
+ return null;
+ }
+
+ /* get relation */
+ String relname = pn.getChild("name").getTerminal();
+ assert relname != null;
+ RelationDescriptor rd = lookupRelation(relname);
+
+ if (rd == null) {
+ er.report(pn, "Undefined relation '" + relname + "'");
+ return null;
+ }
+
+ Expr left = parse_expr(pn.getChild("left").getChild("expr"));
+ Expr right = parse_expr(pn.getChild("right").getChild("expr"));
+
+ if ((left == null) || (right == null)) {
+ return null;
+ }
+
+ return new TupleOfExpr(left, right, rd);
+ }
+
+ private Expr parse_simple_expr(ParseNode pn) {
+ if (!precheck(pn, "simple_expr")) {
+ return null;
+ }
+
+ // only locations so far
+ return parse_location(pn.getChild("location"));
+ }
+
+ private Expr parse_location(ParseNode pn) {
+ if (!precheck(pn, "location")) {
+ return null;
+ }
+
+ if (pn.getChild("var") != null) {
+ // should be changed into a namespace check */
+ return new VarExpr(pn.getChild("var").getTerminal());
+ } else if (pn.getChild("cast") != null) {
+ return parse_cast(pn.getChild("cast"));
+ } else if (pn.getChild("dot") != null) {
+ return parse_dot(pn.getChild("dot"));
+ } else {
+ throw new IRException();
+ }
+ }
+
+ private RelationExpr parse_relation(ParseNode pn) {
+ if (!precheck(pn, "relation")) {
+ return null;
+ }
+
+ RelationExpr re = new RelationExpr();
+
+ /* get quantitifer var */
+ VarDescriptor vd = parse_quantifiervar(pn.getChild("quantifiervar"));
+
+ if (vd == null) {
+ return null;
+ }
+
+ // #TBD#: bad name
+ re.setDomain(vd);
+
+ /* grab list of relations */
+ ParseNodeVector relations = pn.getChild("relations").getChildren();
+ assert relations.size() >= 1;
+
+ // #TBD#: verify that the relations are in the correct order and that the
+ // first relation is getting the correct "inv" assigned from "expr"
+
+ /* lets verify that these relations are defined */
+ for (int i = 0; i < relations.size(); i++) {
+ ParseNode rn = relations.elementAt(i);
+ String relname = rn.getLabel();
+ boolean inverse = rn.getChild("inv") != null;
+
+ RelationDescriptor relation = lookupRelation(relname);
+
+ if (relation == null) {
+ /* Semantic Error: relation not definied" */
+ er.report(rn, "Undefined relation '" + relname + "'");
+ return null;
+ }
+
+ re.setRelation(relation, inverse);
+
+ /* if we are not at end of list then create new relation and
+ replace it to chain the relations */
+ if (i + 1 < relations.size()) {
+ re = new RelationExpr(re); // should create relation with domain as older 're'
+ }
+ }
+
+ return re;
+ }
+
+ private SizeofExpr parse_sizeof(ParseNode pn) {
+ if (!precheck(pn, "sizeof")) {
+ return null;
+ }
+
+ /* get setexpr */
+ SetExpr setexpr = parse_setexpr(pn.getChild("setexpr"));
+
+ if (setexpr == null) {
+ return null;
+ }
+
+ return new SizeofExpr(setexpr);
+ }
+
+ private CastExpr parse_cast(ParseNode pn) {
+ if (!precheck(pn, "cast")) {
+ return null;
+ }
+
+ /* get type */
+ String typename = pn.getChild("type").getTerminal();
+ assert typename != null;
+ TypeDescriptor type = lookupType(typename);
+
+ if (type == null) {
+ /* semantic error: undefined type in cast */
+ er.report(pn, "Undefined type '" + typename + "' in cast operator");
+ return null;
+ }
+
+ /* get expr */
+ Expr expr = parse_simple_expr(pn.getChild("simple_expr"));
+
+ if (expr == null) {
+ return null;
+ }
+
+ return new CastExpr(type, expr);
+ }
+
+ private SetExpr parse_setexpr(ParseNode pn) {
+ if (!precheck(pn, "setexpr")) {
+ return null;
+ }
+
+ // #TBD#: setexpr and parse_relation seem to be cousins... is there a reduction/refactor possible?
+
+ if (pn.getChild("set") != null) {
+ String setname = pn.getChild("set").getTerminal();
+ assert setname != null;
+ SetDescriptor sd = lookupSet(setname);
+
+ if (sd == null) {
+ er.report(pn, "Unknown or undefined set '" + setname + "'");
+ return null;
+ } else {
+ return new SetExpr(sd);
+ }
+ } else if (pn.getChild("dot") != null) {
+ VarDescriptor vd = parse_quantifiervar(pn.getChild("dot").getChild("quantifiervar"));
+ RelationDescriptor relation = lookupRelation(pn.getChild("dot").getChild("relation").getTerminal());
+ return new ImageSetExpr(vd, relation);
+ } else if (pn.getChild("dotinv") != null) {
+ VarDescriptor vd = parse_quantifiervar(pn.getChild("dotinv").getChild("quantifiervar"));
+ RelationDescriptor relation = lookupRelation(pn.getChild("dotinv").getChild("relation").getTerminal());
+ return new ImageSetExpr(ImageSetExpr.INVERSE, vd, relation);
+ } else {
+ throw new IRException();
+ }
+ }
+
+ private VarDescriptor parse_quantifiervar(ParseNode pn) {
+ if (!precheck(pn, "quantifiervar")) {
+ return null;
+ }
+
+ /* get var */
+ String varname = pn.getTerminal();
+ assert varname != null;
+
+ /* NOTE: quantifier var's are only found in the constraints and
+ model definitions... therefore we can do a semantic check here
+ to make sure that the variables exist in the symbol table */
+
+ /* NOTE: its assumed that the symbol table stack is appropriately
+ set up with the parent quantifier symbol table */
+ assert !sts.empty();
+
+ /* do semantic check and if valid, add it to symbol table
+ and add it to the quantifier as well */
+ if (sts.peek().contains(varname)) {
+ return new VarDescriptor(varname);
+ } else {
+ /* Semantic Error: undefined variable */
+ er.report(pn, "Undefined variable '" + varname + "'");
+ return null;
+ }
+ }
+
+ private LiteralExpr parse_literal(ParseNode pn) {
+ if (!precheck(pn, "literal")) {
+ return null;
+ }
+
+ if (pn.getChild("boolean") != null) {
+ if (pn.getChild("boolean").getChild("true") != null) {
+ return new BooleanLiteralExpr(true);
+ } else {
+ return new BooleanLiteralExpr(false);
+ }
+ } else if (pn.getChild("decimal") != null) {
+ String integer = pn.getChild("decimal").getTerminal();
+
+ /* Check for integer literal overflow */
+ BigInteger intLitBI = new BigInteger(integer);
+ BigInteger intMax = new BigInteger("" + Integer.MAX_VALUE);
+ BigInteger intMin = new BigInteger("" + Integer.MIN_VALUE);
+ int value;
+
+ if (intLitBI.compareTo(intMin) < 0) {
+ value = Integer.MIN_VALUE;
+ er.warn(pn, "Integer literal overflow");
+ } else if (intLitBI.compareTo(intMax) > 0) {
+ value = Integer.MAX_VALUE;
+ er.warn(pn, "Integer literal overflow");
+ } else {
+ /* no truncation needed */
+ value = Integer.parseInt(integer);
+ }
+
+ return new IntegerLiteralExpr(value);
+ } else if (pn.getChild("token") != null) {
+ return new TokenLiteralExpr(pn.getChild("token").getTerminal());
+ } else if (pn.getChild("string") != null) {
+ throw new IRException("string unsupported");
+ } else if (pn.getChild("char") != null) {
+ throw new IRException("char unsupported");
+ } else {
+ throw new IRException("unknown literal expression type.");
+ }
+ }
+
+ private OpExpr parse_operator(ParseNode pn) {
+ if (!precheck(pn, "operator")) {
+ return null;
+ }
+
+ String opname = pn.getChild("op").getTerminal();
+
+ Opcode opcode;
+
+ if (opname.equals("add")) {
+ opcode = Opcode.ADD;
+ } else if (opname.equals("sub")) {
+ opcode = Opcode.SUB;
+ } else if (opname.equals("mult")) {
+ opcode = Opcode.MULT;
+ } else if (opname.equals("div")) {
+ opcode = Opcode.DIV;
+ } else if (opname.equals("and")) {
+ opcode = Opcode.AND;
+ } else if (opname.equals("or")) {
+ opcode = Opcode.OR;
+ } else if (opname.equals("not")) {
+ opcode = Opcode.NOT;
+ } else if (opname.equals("gt")) {
+ opcode = Opcode.GT;
+ } else if (opname.equals("ge")) {
+ opcode = Opcode.GE;
+ } else if (opname.equals("lt")) {
+ opcode = Opcode.LT;
+ } else if (opname.equals("le")) {
+ opcode = Opcode.LE;
+ } else if (opname.equals("eq")) {
+ opcode = Opcode.EQ;
+ } else if (opname.equals("ne")) {
+ opcode = Opcode.NE;
+ } else {
+ er.report(pn, "Unsupported operation: " + opname);
+ return null;
+ }
+
+ Expr left = parse_expr(pn.getChild("left").getChild("expr"));
+ Expr right = null;
+
+ if (pn.getChild("right") != null) {
+ right = parse_expr(pn.getChild("right").getChild("expr"));
+ }
+
+ if (left == null) {
+ return null;
+ }
+
+ if (right == null && opcode != Opcode.NOT) {
+ er.report(pn, "Two arguments required.");
+ return null;
+ }
+
+ return new OpExpr(opcode, left, right);
+ }
+
+ private DotExpr parse_dot(ParseNode pn) {
+ if (!precheck(pn, "dot")) {
+ return null;
+ }
+
+ Expr left = parse_simple_expr(pn.getChild("simple_expr"));
+
+ if (left == null) {
+ return null;
+ }
+
+ String field = pn.getChild("field").getTerminal();
+
+ Expr index = null;
+
+ if (pn.getChild("index") != null) {
+ index = parse_expr(pn.getChild("index").getChild("expr"));
+
+ if (index == null) {
+ return null;
+ }
+ }
+
+ return new DotExpr(left, field, index);
+ }
+
+}
+
--- /dev/null
+/**
+ * SetDescriptor
+ *
+ * represents a set in the model space
+ */
+
+package MCC.IR;
+import java.util.*;
+
+public class SetDescriptor extends Descriptor {
+
+ TypeDescriptor type;
+ boolean partition;
+ Vector subsets;
+
+ public SetDescriptor(String name) {
+ super(name);
+ subsets = new Vector();
+ partition = false;
+ }
+
+ public static Set expand(Set descriptors) {
+ HashSet expanded = new HashSet();
+ Iterator d = descriptors.iterator();
+
+ while (d.hasNext()) {
+ Descriptor descriptor = (Descriptor) d.next();
+
+ if (descriptor instanceof SetDescriptor) {
+ expanded.addAll(((SetDescriptor) descriptor).allSubsets());
+ }
+ }
+
+ expanded.addAll(descriptors);
+ return expanded;
+ }
+
+ public boolean isPartition() {
+ return partition;
+ }
+
+ public void isPartition(boolean newvalue) {
+ partition = newvalue;
+ }
+
+ public void setType(TypeDescriptor td) {
+ type = td;
+ }
+
+ public TypeDescriptor getType() {
+ return type;
+ }
+
+ public void addSubset(SetDescriptor sd) {
+ subsets.addElement(sd);
+ }
+
+ public Vector getSubsets() {
+ return subsets;
+ }
+
+ public Iterator subsets() {
+ return subsets.iterator();
+ }
+
+ public boolean isSubset(SetDescriptor sd) {
+ if (sd == this) {
+ return true;
+ }
+
+ for (int i = 0; i < subsets.size(); i++) {
+ SetDescriptor subset = (SetDescriptor) subsets.elementAt(i);
+ if (subset.isSubset(sd)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public Set allSubsets() {
+ Set v = new HashSet();
+ v.add(this);
+
+ for (int i = 0; i < subsets.size(); i++) {
+ SetDescriptor subset = (SetDescriptor) subsets.elementAt(i);
+ v.addAll(subset.allSubsets());
+ }
+
+ return v;
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class SetExpr extends Expr {
+
+ SetDescriptor sd;
+
+ public SetExpr(SetDescriptor sd) {
+ this.sd = sd;
+ }
+
+ public SetExpr() {
+ this.sd = null;
+ }
+
+ public Set getRequiredDescriptors() {
+ HashSet v = new HashSet();
+ v.add(sd);
+ return v;
+ }
+
+ public void generate(CodeWriter writer, VarDescriptor vd) {
+ throw new IRException("unsupported");
+ }
+
+ public void generate_set(CodeWriter writer, VarDescriptor vd) {
+ writer.outputline("Set " + vd.getSafeSymbol() + " = " + sd.getSafeSymbol() + "_hash;");
+ }
+
+ public void prettyPrint(PrettyPrinter pp) {
+ pp.output(sd.getSafeSymbol());
+ }
+
+ public TypeDescriptor typecheck(SemanticAnalyzer sa) {
+ this.td = sd.getType();
+ return this.td;
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class SetInclusion extends Inclusion {
+
+ Expr elementexpr;
+ SetDescriptor set;
+
+ public SetInclusion(Expr elementexpr, SetDescriptor set) {
+ this.elementexpr = elementexpr;
+ this.set = set;
+ }
+
+ public Set getTargetDescriptors() {
+ HashSet v = new HashSet();
+ v.add(set);
+ return v;
+ }
+
+ public Set getRequiredDescriptors() {
+ return elementexpr.getRequiredDescriptors();
+ }
+
+ public void generate(CodeWriter writer) {
+ VarDescriptor vd = VarDescriptor.makeNew("element");
+ elementexpr.generate(writer, vd);
+ writer.outputline(set.getSafeSymbol() + "_hash->add((int)" + vd.getSafeSymbol() + ", (int)" + vd.getSafeSymbol() + ");");
+ //writer.outputline("printf(\"" + set.getSafeSymbol() + " (add): %d\\n\", " + vd.getSafeSymbol() + ");");
+ }
+
+ public boolean typecheck(SemanticAnalyzer sa) {
+ TypeDescriptor td = elementexpr.typecheck(sa);
+
+ if (td == null) {
+ return false;
+ }
+
+ TypeDescriptor settype = set.getType();
+
+ if (!td.equals(settype)) {
+ sa.getErrorReporter().report(null, "Type mismatch: attempting to test for types '" + td.getSymbol() + "' in set of type '" + settype.getSymbol() + "'");
+ return false;
+ }
+
+ return true;
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class SetQuantifier extends Quantifier {
+
+ VarDescriptor var;
+ SetDescriptor set;
+
+ public SetQuantifier() {
+ this.var = null;
+ }
+
+ public void setVar(VarDescriptor vd) {
+ this.var = vd;
+ }
+
+ public void setSet(SetDescriptor sd) {
+ this.set = sd;
+ }
+
+ public Set getRequiredDescriptors() {
+ HashSet v = new HashSet();
+ v.add(set);
+ return v;
+ }
+
+ public SetDescriptor getSet() {
+ return set;
+ }
+
+ public String toString() {
+ return "set quantifier " + var.getSymbol() + " in " + set.getSymbol();
+ }
+
+ public void generate_open(CodeWriter writer) {
+ writer.outputline("for (SimpleIterator* " + var.getSafeSymbol() + "_iterator = " + set.getSafeSymbol() + "_hash->iterator(); " + var.getSafeSymbol() + "_iterator->hasNext(); ) {");
+ writer.indent();
+ writer.outputline(var.getType().getGenerateType() + " " + var.getSafeSymbol() + " = (" + var.getType().getGenerateType() + ") " + var.getSafeSymbol() + "_iterator->next();");
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.Vector;
+
+public class SimpleIRErrorReporter implements IRErrorReporter {
+
+ public boolean error;
+
+ String filename;
+ Vector messages;
+
+
+ public SimpleIRErrorReporter () {
+ messages = new Vector();
+ error = false;
+ filename = null;
+ }
+
+ public void setFilename(String filename) {
+ this.filename = new String(filename + ":");
+ }
+
+ public void report(ParseNode v, String s) {
+
+ LinedMessage sem = new LinedMessage();
+ sem.error = true;
+ sem.pn = v;
+ sem.message = s;
+
+ add(sem);
+
+ error = true;
+ }
+
+ public void warn(ParseNode v, String s) {
+
+ LinedMessage sem = new LinedMessage();
+ sem.error = false;
+ sem.pn = v;
+ sem.message = s;
+
+ add(sem);
+ }
+
+ private void add(LinedMessage sem) {
+
+ if (sem.pn == null) {
+ messages.addElement(sem);
+ return;
+ }
+
+ int i;
+ for (i = 0; i < messages.size(); i++) {
+
+ LinedMessage cur = (LinedMessage)messages.elementAt(i);
+
+ if (cur.pn.getLine() > sem.pn.getLine()) {
+ break;
+ }
+ }
+
+ messages.insertElementAt(sem, i);
+ }
+
+ public String toString() {
+ String output = new String();
+
+ for (int i = 0; i < messages.size(); i++) {
+ LinedMessage sem = (LinedMessage)messages.elementAt(i);
+ if (sem.error) {
+ output += "error";
+ } else {
+ output += "warning";
+ }
+
+ if (sem.pn != null) {
+ output += " (" + filename + sem.pn.getLine() + "): ";
+ } else {
+ output += " : ";
+ }
+
+ output += sem.message;
+ output += "\n";
+ }
+ return output;
+ }
+}
+
+class LinedMessage {
+ boolean error;
+ public ParseNode pn;
+ public String message;
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class SizeofExpr extends Expr {
+
+ SetExpr setexpr;
+
+ public SizeofExpr(SetExpr setexpr) {
+ if (setexpr == null) {
+ throw new NullPointerException();
+ }
+
+ this.setexpr = setexpr;
+ }
+
+ public Set getRequiredDescriptors() {
+ return setexpr.getRequiredDescriptors();
+ }
+
+ public void generate(CodeWriter writer, VarDescriptor dest) {
+ VarDescriptor sd = VarDescriptor.makeNew();
+ setexpr.generate_set(writer, sd);
+ writer.outputline("int " + dest.getSafeSymbol() + " = " + sd.getSafeSymbol() + ".size();");
+ }
+
+ public void prettyPrint(PrettyPrinter pp) {
+ pp.output("sizeof(");
+ setexpr.prettyPrint(pp);
+ pp.output(")");
+ }
+
+ public TypeDescriptor typecheck(SemanticAnalyzer sa) {
+ this.td = ReservedTypeDescriptor.INT;
+ return this.td;
+ }
+
+
+}
--- /dev/null
+package MCC.IR;
+
+/**
+ * StructureTypeDescriptor
+ *
+ * represents structure types
+ */
+
+import java.util.*;
+
+public class StructureTypeDescriptor extends TypeDescriptor {
+
+ TypeDescriptor subtype;
+
+ Hashtable fields = new Hashtable(); /* fast lookups */
+ Vector fieldlist = new Vector(); /* ordering information */
+ Hashtable labels = new Hashtable();
+
+ public StructureTypeDescriptor(String name) {
+ super(name);
+ }
+
+ public TypeDescriptor getGenerateType() {
+ return ReservedTypeDescriptor.INT;
+ }
+
+ public Enumeration getFieldKeys() {
+ return fields.keys();
+ }
+
+ private Vector getFieldSizes() {
+ Vector fieldsizes = new Vector();
+
+ for (int i = 0; i < fieldlist.size(); i++) {
+ FieldDescriptor fd = (FieldDescriptor) fieldlist.elementAt(i);
+ TypeDescriptor td = fd.getType();
+ boolean ptr = fd.getPtr();
+
+ Expr basesize;
+ if (ptr) { /* ptrs are 32bits */
+ basesize = new IntegerLiteralExpr(32);
+ } else {
+ basesize = td.getSizeExpr();
+ }
+
+ if (fd instanceof ArrayDescriptor) {
+ Expr totalsize = new OpExpr(Opcode.MULT, basesize, ((ArrayDescriptor) fd).getIndexBound());
+ fieldsizes.addElement(totalsize);
+ } else {
+ fieldsizes.addElement(basesize);
+ }
+ }
+
+ return fieldsizes;
+ }
+
+ public Expr getSizeExpr() {
+ Vector fieldsizes = getFieldSizes();
+
+ /* we've got the field sizes! now return the addition! */
+ Expr size = new IntegerLiteralExpr(0);
+
+ for (int i = 0; i < fieldsizes.size(); i++) {
+ Expr fieldsize = (Expr) fieldsizes.elementAt(i);
+ size = new OpExpr(Opcode.ADD, fieldsize, size);
+ }
+
+ return size;
+ }
+
+ public Expr getOffsetExpr(FieldDescriptor field) {
+ Vector fieldsizes = getFieldSizes();
+
+ // #ATTN#: getOffsetExpr needs to be called with the fielddescriptor obect that is in teh vector list
+ // this means that if the field is an arraydescriptor you have to call getOffsetExpr with the array
+
+ /* we've got the field sizes! now return the addition! */
+ Expr size = new IntegerLiteralExpr(0);
+
+ for (int i = 0; i < fieldsizes.size(); i++) {
+ FieldDescriptor fd = (FieldDescriptor)fieldlist.elementAt(i);
+
+ if (fd == field) { /* stop, reached target field */
+ break;
+ }
+
+ Expr fieldsize = (Expr) fieldsizes.elementAt(i);
+ size = new OpExpr(Opcode.ADD, fieldsize, size);
+ }
+
+ return size;
+ }
+
+ public Iterator getFields() {
+ return fields.values().iterator();
+ }
+
+ public Iterator getLabels() {
+ return labels.values().iterator();
+ }
+
+ public FieldDescriptor getField(String name) {
+ return (FieldDescriptor) fields.get(name);
+ }
+
+ public LabelDescriptor getLabel(String name) {
+ return (LabelDescriptor) labels.get(name);
+ }
+
+ public void addField(FieldDescriptor fd) {
+ if (getField(fd.getSymbol()) != null) {
+ throw new IRException("Can not overwrite a field once it has been added.");
+ }
+ fields.put(fd.getSymbol(), fd);
+ fieldlist.addElement(fd);
+ }
+
+ public void addLabel(LabelDescriptor ld) {
+ if (getLabel(ld.getSymbol()) != null) {
+ throw new IRException("Can not overwrite a label once it has been added.");
+ }
+ labels.put(ld.getSymbol(), ld);
+ }
+
+ public TypeDescriptor getSubType() {
+ return subtype;
+ }
+
+ public void setSubType(TypeDescriptor td) {
+ subtype = td;
+ }
+
+ public boolean isSubtypeOf(TypeDescriptor td) {
+ if (td == this) {
+ return true;
+ } else {
+ return subtype.isSubtypeOf(td);
+ }
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class SymbolTable {
+
+ private Hashtable table;
+ private SymbolTable parent;
+
+ public SymbolTable() {
+ table = new Hashtable();
+ this.parent = null;
+ }
+
+ public SymbolTable(SymbolTable parent) {
+ table = new Hashtable();
+ this.parent = parent;
+ }
+
+ //public void add(String name, Descriptor d) {
+ //table.put(name, d);
+ //}
+
+ public void add(Descriptor d) {
+ table.put(d.getSymbol(), d);
+ }
+
+ public void add(String name, Descriptor d) {
+ table.put(name, d);
+
+ }
+
+ public void dump() {
+ Enumeration e = getDescriptors();
+ while (e.hasMoreElements()) {
+ Descriptor d = (Descriptor) e.nextElement();
+ System.out.println(d.getSymbol());
+ }
+ if (parent != null) {
+ System.out.println("parent:");
+ parent.dump();
+ }
+ }
+
+ public Descriptor get(String name) {
+ Descriptor d = (Descriptor) table.get(name);
+ if (d == null && parent != null) {
+ return parent.get(name);
+ } else {
+ return d;
+ }
+ }
+
+ public Descriptor getFromSameScope(String name) {
+ return (Descriptor)table.get(name);
+ }
+
+ public Enumeration getNames() {
+ return table.keys();
+ }
+
+ public Enumeration getDescriptors() {
+ return table.elements();
+ }
+
+ public Iterator descriptors() {
+ return table.values().iterator();
+ }
+
+ public Vector getAllDescriptors() {
+ Vector d;
+ if (parent == null) {
+ d = new Vector();
+ } else {
+ d = parent.getAllDescriptors();
+ }
+
+ Enumeration e = getDescriptors();
+ while(e.hasMoreElements()) {
+ d.addElement(e.nextElement());
+ }
+
+ return d;
+ }
+
+ public boolean contains(String name) {
+ return (get(name) != null);
+ }
+
+
+ public int size() {
+ return table.size();
+ }
+
+ public int sizeAll() {
+ if (parent != null) {
+ return parent.sizeAll() + table.size();
+ } else {
+ return table.size();
+ }
+ }
+
+ public SymbolTable getParent() {
+ return parent;
+ }
+
+ public void setParent(SymbolTable parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * Adds contents of st2.table to this.table and returns a
+ * Vector of shared names, unless there are no shared names,
+ * in which case returns null.
+ */
+ public Vector merge(SymbolTable st2) {
+ Vector v = new Vector();
+ Enumeration names = st2.table.keys();
+
+ while (names.hasMoreElements()) {
+ Object o = names.nextElement();
+
+ if (table.containsKey(o)) {
+ v.addElement(o);
+ } else {
+ table.put(o, st2.table.get(o));
+ }
+ }
+
+ if (v.size() == 0) {
+ return null;
+ } else {
+ return v;
+ }
+ }
+
+ public String toString() {
+ return "ST: " + table.toString();
+ }
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class SymbolTableStack {
+
+ SymbolTable st;
+
+ SymbolTableStack() {
+ st = null;
+ }
+
+ SymbolTableStack(SymbolTable st) {
+ this.st = st;
+ }
+
+ boolean empty() {
+ return st == null;
+ }
+
+ SymbolTable peek() {
+ return st;
+ }
+
+ SymbolTable pop() {
+ if (st == null) {
+ throw new IRException("SymbolTableStack: tried to pop empty stack.");
+ }
+
+ SymbolTable lastst = st;
+ st = st.getParent();
+ return lastst;
+ }
+
+ // Link and push.
+ void push(SymbolTable st) {
+ if (st != null) {
+ st.setParent(this.st);
+ }
+
+ this.st = st;
+ }
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class TokenLiteralExpr extends LiteralExpr {
+
+ String token;
+ Integer num;
+
+ static int count = 100;
+ static Hashtable tokens = new Hashtable();
+
+ public TokenLiteralExpr(String token) {
+ this.token = token;
+ td = ReservedTypeDescriptor.INT;
+
+ if (tokens.contains(token)) {
+ num = (Integer) tokens.get(token);
+ } else {
+ num = new Integer(count++);
+ tokens.put(token, num);
+ }
+ }
+
+ public String getValue() {
+ return token;
+ }
+
+ public void generate(CodeWriter writer, VarDescriptor dest) {
+ writer.outputline("int " + dest.getSafeSymbol() + " = " + num.toString().toString() + ";");
+ }
+
+ public void prettyPrint(PrettyPrinter pp) {
+ pp.output("{" + token + " = " + num + "}");
+ }
+
+ public TypeDescriptor typecheck(SemanticAnalyzer sa) {
+ td = ReservedTypeDescriptor.INT;
+ return td;
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class TokenSetDescriptor extends SetDescriptor {
+
+ private static int count = 0;
+ Vector literals = new Vector();
+
+ public TokenSetDescriptor() {
+ super("toketsetdescriptor" + count++);
+ }
+
+ public void addLiteral(LiteralExpr lit) {
+ literals.addElement(lit);
+ }
+
+ public TypeDescriptor getType() {
+ return ReservedTypeDescriptor.INT;
+ }
+
+ public void setType(TypeDescriptor td) {
+ throw new IRException("invalid");
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class TupleOfExpr extends Expr {
+
+ Expr left = null;
+ Expr right = null;
+ RelationDescriptor relation = null;
+
+ public TupleOfExpr(Expr left, Expr right, RelationDescriptor relation) {
+ if ((left == null) || (right == null) || (relation == null)) {
+ throw new NullPointerException();
+ }
+
+ this.left = left;
+ this.right = right;
+ this.relation = relation;
+ }
+
+ public Set getRequiredDescriptors() {
+ Set v = left.getRequiredDescriptors();
+ v.addAll(right.getRequiredDescriptors());
+ v.add(relation);
+ return v;
+ }
+
+ public void generate(CodeWriter writer, VarDescriptor dest) {
+ VarDescriptor ld = VarDescriptor.makeNew();
+ left.generate(writer, ld);
+
+ VarDescriptor rd = VarDescriptor.makeNew();
+ right.generate(writer, rd);
+
+ writer.outputline("int " + dest.getSafeSymbol() + " = " +
+ relation.getSafeSymbol() + "_hash->get(" + ld.getSafeSymbol() +
+ ") == " + rd.getSafeSymbol() + ";");
+ }
+
+ public void prettyPrint(PrettyPrinter pp) {
+ pp.output("<");
+ left.prettyPrint(pp);
+ pp.output(", ");
+ right.prettyPrint(pp);
+ pp.output("> in? " + relation.getSafeSymbol());
+ }
+
+ public TypeDescriptor typecheck(SemanticAnalyzer sa) {
+ TypeDescriptor ld = left.typecheck(sa);
+ TypeDescriptor rd = right.typecheck(sa);
+
+ if (ld == null || rd == null) {
+ return null;
+ }
+
+ boolean ok = true;
+
+ if (ld != relation.getDomain().getType()) {
+ sa.getErrorReporter().report(null, "Type of left element '" + ld.getSymbol() + "' must match domain type '" + relation.getDomain().getType().getSymbol() + "'");
+ ok = false;
+ }
+
+ if (rd != relation.getRange().getType()) {
+ sa.getErrorReporter().report(null, "Type of right element '" + rd.getSymbol() + "' must match range type '" + relation.getRange().getType().getSymbol() + "'");
+ ok = false;
+ }
+
+ if (!ok) {
+ return null;
+ }
+
+ this.td = ReservedTypeDescriptor.INT;
+ return this.td;
+ }
+
+
+}
--- /dev/null
+package MCC.IR;
+
+/**
+ * TypeDescriptor
+ *
+ * represents types in the language (bit, short, etc. as well as structures)
+ */
+
+public abstract class TypeDescriptor extends Descriptor {
+
+ public TypeDescriptor(String name) {
+ super(name);
+ }
+
+ public boolean isSubtypeOf(TypeDescriptor td) {
+ return false;
+ }
+
+ public TypeDescriptor getGenerateType() {
+ return this;
+ }
+
+ public abstract Expr getSizeExpr();
+
+}
--- /dev/null
+package MCC.IR;
+
+public class VarDescriptor extends Descriptor {
+
+ private static int count = 0;
+
+ TypeDescriptor td = null;
+
+ public VarDescriptor(String name) {
+ super(name);
+ }
+
+ public VarDescriptor(String name, TypeDescriptor td) {
+ super(name);
+ this.td = td;
+ }
+
+ public VarDescriptor(String name, String safename, TypeDescriptor td) {
+ super(name, safename);
+ this.td = td;
+ }
+
+ public void setType(TypeDescriptor td) {
+ this.td = td;
+ }
+
+ public TypeDescriptor getType() {
+ return td;
+ }
+
+ public static VarDescriptor makeNew() {
+ return makeNew("tempvar");
+ }
+
+ public static VarDescriptor makeNew(String name) {
+ return new VarDescriptor(name + count++);
+ }
+
+}
--- /dev/null
+package MCC.IR;
+
+import java.util.*;
+
+public class VarExpr extends Expr {
+
+ String varname;
+ VarDescriptor vd = null;
+
+ public VarExpr(String varname) {
+ this.varname = varname;
+ }
+
+ public Set getRequiredDescriptors() {
+ return new HashSet();
+ }
+
+ public void generate(CodeWriter writer, VarDescriptor dest) {
+ writer.outputline(vd.getType().getGenerateType().getSafeSymbol() + " " + dest.getSafeSymbol() +
+ " = (" + vd.getType().getGenerateType().getSafeSymbol() + ") " + vd.getSafeSymbol() + ";");
+ }
+
+ public void prettyPrint(PrettyPrinter pp) {
+ pp.output(varname);
+ }
+
+ public TypeDescriptor typecheck(SemanticAnalyzer sa) {
+ vd = (VarDescriptor) sa.getSymbolTable().get(varname);
+
+ if (vd == null) {
+ System.out.println(varname);
+ sa.getErrorReporter().report(null, "Undefined variable '" + varname + "'");
+ return null;
+ }
+
+ assert vd.getType() != null;
+
+ this.td = vd.getType();
+ return this.td;
+ }
+
+}
--- /dev/null
+
+package MCC.IR;
+
+/**
+ * The Walkable interface specifies a set of methods that defines a web.
+ */
+
+public interface Walkable {
+
+ /**
+ * Returns the name of the node
+ */
+ public String getNodeName();
+
+
+ /**
+ * Returns the number of neighbors from this node
+ */
+ public int getNeighborCount();
+
+
+ /**
+ * Returns a specific neighbor
+ */
+ public Object getNeighbor(int index);
+
+ /**
+ * Returns a pretty print of the representation of the node.
+ *
+ * @param indent number of blank spaces to skip for a new line
+ * @param recursive if true, recursively print children
+ */
+ public String PPrint(int indent, boolean recursive);
+}
+