From: droy Date: Mon, 7 Jul 2003 16:14:57 +0000 (+0000) Subject: IR X-Git-Url: http://plrg.eecs.uci.edu/git/?p=repair.git;a=commitdiff_plain;h=cbe945a51aa2e383c3ab5d14024a4a2edea4c84a IR --- diff --git a/Repair/RepairCompiler/MCC/IR/ArrayDescriptor.java b/Repair/RepairCompiler/MCC/IR/ArrayDescriptor.java new file mode 100755 index 0000000..480ea4b --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/ArrayDescriptor.java @@ -0,0 +1,41 @@ +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(); + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/BooleanLiteralExpr.java b/Repair/RepairCompiler/MCC/IR/BooleanLiteralExpr.java new file mode 100755 index 0000000..d0729e6 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/BooleanLiteralExpr.java @@ -0,0 +1,31 @@ +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; + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/CastExpr.java b/Repair/RepairCompiler/MCC/IR/CastExpr.java new file mode 100755 index 0000000..83a1ddb --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/CastExpr.java @@ -0,0 +1,59 @@ +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; + } + +} + + + + + + + + diff --git a/Repair/RepairCompiler/MCC/IR/CodeWriter.java b/Repair/RepairCompiler/MCC/IR/CodeWriter.java new file mode 100755 index 0000000..d36ee72 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/CodeWriter.java @@ -0,0 +1,11 @@ +package MCC.IR; + +public interface CodeWriter extends PrettyPrinter{ + + public void outputline(String s); + public void indent(); + public void unindent(); + + public SymbolTable getSymbolTable(); + +} diff --git a/Repair/RepairCompiler/MCC/IR/ComparisonPredicate.java b/Repair/RepairCompiler/MCC/IR/ComparisonPredicate.java new file mode 100755 index 0000000..1e28b63 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/ComparisonPredicate.java @@ -0,0 +1,51 @@ +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; + } + +} + diff --git a/Repair/RepairCompiler/MCC/IR/Constraint.java b/Repair/RepairCompiler/MCC/IR/Constraint.java new file mode 100755 index 0000000..ec216b6 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/Constraint.java @@ -0,0 +1,75 @@ +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; + } + +} + diff --git a/Repair/RepairCompiler/MCC/IR/DependencyBuilder.java b/Repair/RepairCompiler/MCC/IR/DependencyBuilder.java new file mode 100755 index 0000000..975ea60 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/DependencyBuilder.java @@ -0,0 +1,182 @@ +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(); + } + + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/Descriptor.java b/Repair/RepairCompiler/MCC/IR/Descriptor.java new file mode 100755 index 0000000..99eb8d9 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/Descriptor.java @@ -0,0 +1,36 @@ +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; + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/DotExpr.java b/Repair/RepairCompiler/MCC/IR/DotExpr.java new file mode 100755 index 0000000..fe293d1 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/DotExpr.java @@ -0,0 +1,228 @@ +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; + } + + + } + +} + diff --git a/Repair/RepairCompiler/MCC/IR/ElementOfExpr.java b/Repair/RepairCompiler/MCC/IR/ElementOfExpr.java new file mode 100755 index 0000000..51941f9 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/ElementOfExpr.java @@ -0,0 +1,56 @@ +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; + } + +} + diff --git a/Repair/RepairCompiler/MCC/IR/Expr.java b/Repair/RepairCompiler/MCC/IR/Expr.java new file mode 100755 index 0000000..b5481c3 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/Expr.java @@ -0,0 +1,24 @@ +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); + +} diff --git a/Repair/RepairCompiler/MCC/IR/FieldDescriptor.java b/Repair/RepairCompiler/MCC/IR/FieldDescriptor.java new file mode 100755 index 0000000..352a41b --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/FieldDescriptor.java @@ -0,0 +1,44 @@ +/** + * 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(); + } + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/ForQuantifier.java b/Repair/RepairCompiler/MCC/IR/ForQuantifier.java new file mode 100755 index 0000000..2b354f7 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/ForQuantifier.java @@ -0,0 +1,73 @@ +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; + } + +} + + + + + + + + + + diff --git a/Repair/RepairCompiler/MCC/IR/GraphNode.java b/Repair/RepairCompiler/MCC/IR/GraphNode.java new file mode 100755 index 0000000..8059be3 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/GraphNode.java @@ -0,0 +1,263 @@ +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 */ + +} diff --git a/Repair/RepairCompiler/MCC/IR/IRErrorReporter.java b/Repair/RepairCompiler/MCC/IR/IRErrorReporter.java new file mode 100755 index 0000000..3b013f0 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/IRErrorReporter.java @@ -0,0 +1,7 @@ +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); +} diff --git a/Repair/RepairCompiler/MCC/IR/IRException.java b/Repair/RepairCompiler/MCC/IR/IRException.java new file mode 100755 index 0000000..d9542c9 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/IRException.java @@ -0,0 +1,23 @@ +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"); + } +} + diff --git a/Repair/RepairCompiler/MCC/IR/ImageSetExpr.java b/Repair/RepairCompiler/MCC/IR/ImageSetExpr.java new file mode 100755 index 0000000..ac255ca --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/ImageSetExpr.java @@ -0,0 +1,43 @@ +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"); + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/Inclusion.java b/Repair/RepairCompiler/MCC/IR/Inclusion.java new file mode 100755 index 0000000..0fe01da --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/Inclusion.java @@ -0,0 +1,18 @@ +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); + +} + diff --git a/Repair/RepairCompiler/MCC/IR/InclusionPredicate.java b/Repair/RepairCompiler/MCC/IR/InclusionPredicate.java new file mode 100755 index 0000000..0944327 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/InclusionPredicate.java @@ -0,0 +1,28 @@ +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(); + } + +} + diff --git a/Repair/RepairCompiler/MCC/IR/IntegerLiteralExpr.java b/Repair/RepairCompiler/MCC/IR/IntegerLiteralExpr.java new file mode 100755 index 0000000..46a8111 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/IntegerLiteralExpr.java @@ -0,0 +1,29 @@ +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; + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/LabelDescriptor.java b/Repair/RepairCompiler/MCC/IR/LabelDescriptor.java new file mode 100755 index 0000000..30f17a2 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/LabelDescriptor.java @@ -0,0 +1,39 @@ +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(); + } +} diff --git a/Repair/RepairCompiler/MCC/IR/LiteralExpr.java b/Repair/RepairCompiler/MCC/IR/LiteralExpr.java new file mode 100755 index 0000000..df14ed1 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/LiteralExpr.java @@ -0,0 +1,11 @@ +package MCC.IR; + +import java.util.*; + +public abstract class LiteralExpr extends Expr { + + public Set getRequiredDescriptors() { + return new HashSet(); + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/LogicStatement.java b/Repair/RepairCompiler/MCC/IR/LogicStatement.java new file mode 100755 index 0000000..ea44606 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/LogicStatement.java @@ -0,0 +1,55 @@ +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; + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/MissingSetDescriptor.java b/Repair/RepairCompiler/MCC/IR/MissingSetDescriptor.java new file mode 100755 index 0000000..eaa5144 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/MissingSetDescriptor.java @@ -0,0 +1,40 @@ +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(); + } +} diff --git a/Repair/RepairCompiler/MCC/IR/MissingTypeDescriptor.java b/Repair/RepairCompiler/MCC/IR/MissingTypeDescriptor.java new file mode 100755 index 0000000..0df3caa --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/MissingTypeDescriptor.java @@ -0,0 +1,19 @@ +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"); + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/NaiveGenerator.java b/Repair/RepairCompiler/MCC/IR/NaiveGenerator.java new file mode 100755 index 0000000..d4af8e5 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/NaiveGenerator.java @@ -0,0 +1,210 @@ +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"); + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/OpExpr.java b/Repair/RepairCompiler/MCC/IR/OpExpr.java new file mode 100755 index 0000000..6ca7d65 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/OpExpr.java @@ -0,0 +1,98 @@ +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; + } + +} + + + + + diff --git a/Repair/RepairCompiler/MCC/IR/Opcode.java b/Repair/RepairCompiler/MCC/IR/Opcode.java new file mode 100755 index 0000000..79a1666 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/Opcode.java @@ -0,0 +1,27 @@ +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("!"); + +} diff --git a/Repair/RepairCompiler/MCC/IR/ParseNode.java b/Repair/RepairCompiler/MCC/IR/ParseNode.java new file mode 100755 index 0000000..4b65354 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/ParseNode.java @@ -0,0 +1,219 @@ +/* + + 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\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) + "\n"; + } + + return output; + } + +} + diff --git a/Repair/RepairCompiler/MCC/IR/ParseNodeDOTVisitor.java b/Repair/RepairCompiler/MCC/IR/ParseNodeDOTVisitor.java new file mode 100755 index 0000000..7a25ff1 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/ParseNodeDOTVisitor.java @@ -0,0 +1,71 @@ +/* + + 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); + } + } +} diff --git a/Repair/RepairCompiler/MCC/IR/ParseNodeVector.java b/Repair/RepairCompiler/MCC/IR/ParseNodeVector.java new file mode 100755 index 0000000..7f330d3 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/ParseNodeVector.java @@ -0,0 +1,27 @@ +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(); + } +} diff --git a/Repair/RepairCompiler/MCC/IR/Predicate.java b/Repair/RepairCompiler/MCC/IR/Predicate.java new file mode 100755 index 0000000..6c1539e --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/Predicate.java @@ -0,0 +1,8 @@ +package MCC.IR; + +import java.util.*; + +public abstract class Predicate extends LogicStatement { + protected Predicate() {} +} + diff --git a/Repair/RepairCompiler/MCC/IR/PrettyPrinter.java b/Repair/RepairCompiler/MCC/IR/PrettyPrinter.java new file mode 100755 index 0000000..f862d3c --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/PrettyPrinter.java @@ -0,0 +1,7 @@ +package MCC.IR; + +import java.util.*; + +public interface PrettyPrinter { + void output(String s); +} diff --git a/Repair/RepairCompiler/MCC/IR/Quantifier.java b/Repair/RepairCompiler/MCC/IR/Quantifier.java new file mode 100755 index 0000000..4185cff --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/Quantifier.java @@ -0,0 +1,10 @@ +package MCC.IR; + +import java.util.*; + +public abstract class Quantifier { + + public abstract Set getRequiredDescriptors(); + + public abstract void generate_open(CodeWriter writer); +} diff --git a/Repair/RepairCompiler/MCC/IR/RelationDescriptor.java b/Repair/RepairCompiler/MCC/IR/RelationDescriptor.java new file mode 100755 index 0000000..61328b7 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/RelationDescriptor.java @@ -0,0 +1,46 @@ +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; + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/RelationExpr.java b/Repair/RepairCompiler/MCC/IR/RelationExpr.java new file mode 100755 index 0000000..6e1380a --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/RelationExpr.java @@ -0,0 +1,126 @@ +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; + } + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/RelationInclusion.java b/Repair/RepairCompiler/MCC/IR/RelationInclusion.java new file mode 100755 index 0000000..f0fd0c4 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/RelationInclusion.java @@ -0,0 +1,62 @@ +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; + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/RelationQuantifier.java b/Repair/RepairCompiler/MCC/IR/RelationQuantifier.java new file mode 100755 index 0000000..ae6886e --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/RelationQuantifier.java @@ -0,0 +1,39 @@ +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();"); + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/ReservedFieldDescriptor.java b/Repair/RepairCompiler/MCC/IR/ReservedFieldDescriptor.java new file mode 100755 index 0000000..e89b938 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/ReservedFieldDescriptor.java @@ -0,0 +1,18 @@ +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++ + "#"); + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/ReservedSetDescriptor.java b/Repair/RepairCompiler/MCC/IR/ReservedSetDescriptor.java new file mode 100755 index 0000000..9667144 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/ReservedSetDescriptor.java @@ -0,0 +1,16 @@ +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); + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/ReservedTypeDescriptor.java b/Repair/RepairCompiler/MCC/IR/ReservedTypeDescriptor.java new file mode 100755 index 0000000..a02dd31 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/ReservedTypeDescriptor.java @@ -0,0 +1,31 @@ +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(); + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/Rule.java b/Repair/RepairCompiler/MCC/IR/Rule.java new file mode 100755 index 0000000..16087e2 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/Rule.java @@ -0,0 +1,80 @@ +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); + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/ScheduleEvent.java b/Repair/RepairCompiler/MCC/IR/ScheduleEvent.java new file mode 100755 index 0000000..ea3cd51 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/ScheduleEvent.java @@ -0,0 +1,11 @@ +package MCC.IR; + +import java.util.*; + +public class ScheduleEvent { + + Vector preconditions; + Vector postconditions; + + +} diff --git a/Repair/RepairCompiler/MCC/IR/SemanticAnalyzer.java b/Repair/RepairCompiler/MCC/IR/SemanticAnalyzer.java new file mode 100755 index 0000000..2f14553 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/SemanticAnalyzer.java @@ -0,0 +1,11 @@ +package MCC.IR; + +import java.util.*; + +public interface SemanticAnalyzer { + + IRErrorReporter getErrorReporter(); + + SymbolTable getSymbolTable(); + +} diff --git a/Repair/RepairCompiler/MCC/IR/SemanticChecker.java b/Repair/RepairCompiler/MCC/IR/SemanticChecker.java new file mode 100755 index 0000000..be4e07d --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/SemanticChecker.java @@ -0,0 +1,1605 @@ +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); + } + +} + diff --git a/Repair/RepairCompiler/MCC/IR/SetDescriptor.java b/Repair/RepairCompiler/MCC/IR/SetDescriptor.java new file mode 100755 index 0000000..6bd62ed --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/SetDescriptor.java @@ -0,0 +1,93 @@ +/** + * 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; + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/SetExpr.java b/Repair/RepairCompiler/MCC/IR/SetExpr.java new file mode 100755 index 0000000..deb9a1b --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/SetExpr.java @@ -0,0 +1,40 @@ +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; + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/SetInclusion.java b/Repair/RepairCompiler/MCC/IR/SetInclusion.java new file mode 100755 index 0000000..deb6ea5 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/SetInclusion.java @@ -0,0 +1,49 @@ +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; + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/SetQuantifier.java b/Repair/RepairCompiler/MCC/IR/SetQuantifier.java new file mode 100755 index 0000000..8ef4804 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/SetQuantifier.java @@ -0,0 +1,42 @@ +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();"); + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/SimpleIRErrorReporter.java b/Repair/RepairCompiler/MCC/IR/SimpleIRErrorReporter.java new file mode 100755 index 0000000..3c64101 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/SimpleIRErrorReporter.java @@ -0,0 +1,93 @@ +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; +} diff --git a/Repair/RepairCompiler/MCC/IR/SizeofExpr.java b/Repair/RepairCompiler/MCC/IR/SizeofExpr.java new file mode 100755 index 0000000..691b135 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/SizeofExpr.java @@ -0,0 +1,39 @@ +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; + } + + +} diff --git a/Repair/RepairCompiler/MCC/IR/StructureTypeDescriptor.java b/Repair/RepairCompiler/MCC/IR/StructureTypeDescriptor.java new file mode 100755 index 0000000..a9fd29c --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/StructureTypeDescriptor.java @@ -0,0 +1,141 @@ +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); + } + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/SymbolTable.java b/Repair/RepairCompiler/MCC/IR/SymbolTable.java new file mode 100755 index 0000000..8bb1c46 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/SymbolTable.java @@ -0,0 +1,140 @@ +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(); + } +} diff --git a/Repair/RepairCompiler/MCC/IR/SymbolTableStack.java b/Repair/RepairCompiler/MCC/IR/SymbolTableStack.java new file mode 100755 index 0000000..06d2ab7 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/SymbolTableStack.java @@ -0,0 +1,43 @@ +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; + } +} diff --git a/Repair/RepairCompiler/MCC/IR/TokenLiteralExpr.java b/Repair/RepairCompiler/MCC/IR/TokenLiteralExpr.java new file mode 100755 index 0000000..7754240 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/TokenLiteralExpr.java @@ -0,0 +1,42 @@ +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; + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/TokenSetDescriptor.java b/Repair/RepairCompiler/MCC/IR/TokenSetDescriptor.java new file mode 100755 index 0000000..65070b2 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/TokenSetDescriptor.java @@ -0,0 +1,26 @@ +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"); + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/TupleOfExpr.java b/Repair/RepairCompiler/MCC/IR/TupleOfExpr.java new file mode 100755 index 0000000..c3fa76e --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/TupleOfExpr.java @@ -0,0 +1,77 @@ +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; + } + + +} diff --git a/Repair/RepairCompiler/MCC/IR/TypeDescriptor.java b/Repair/RepairCompiler/MCC/IR/TypeDescriptor.java new file mode 100755 index 0000000..5392f1b --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/TypeDescriptor.java @@ -0,0 +1,25 @@ +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(); + +} diff --git a/Repair/RepairCompiler/MCC/IR/VarDescriptor.java b/Repair/RepairCompiler/MCC/IR/VarDescriptor.java new file mode 100755 index 0000000..6fca9ce --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/VarDescriptor.java @@ -0,0 +1,39 @@ +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++); + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/VarExpr.java b/Repair/RepairCompiler/MCC/IR/VarExpr.java new file mode 100755 index 0000000..64587da --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/VarExpr.java @@ -0,0 +1,42 @@ +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; + } + +} diff --git a/Repair/RepairCompiler/MCC/IR/Walkable.java b/Repair/RepairCompiler/MCC/IR/Walkable.java new file mode 100755 index 0000000..d605327 --- /dev/null +++ b/Repair/RepairCompiler/MCC/IR/Walkable.java @@ -0,0 +1,35 @@ + +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); +} +