// need to do reasonable things with non demeter classes // // The two visitors in this program work together. They each make a pass // over the program. The GenerateEqualTraversal Generates the vertex // wrappers and the GenerateEdgeTraversal generates the edge wrappers. // Main { // main program (@ public static void main(String args[]) throws Exception { Program parsed = Program.parse(System.in); Program.theProgram = parsed; parsed.GenerateEqualCode(); } @) } Program { traversal GenerateEqualTraversal(GenerateEqualVisitor t) { to { Part }; } traversal GenerateEdgeTraversal(GenerateEdgeVisitor t) { to { Part }; } (@ static Program theProgram; @) (@ void GenerateEqualCode() { GenerateEqualVisitor gpv = new GenerateEqualVisitor(); GenerateEdgeVisitor gev = new GenerateEdgeVisitor(); this.GenerateEqualTraversal(gpv); this.GenerateEdgeTraversal(gev); } @) } GenerateEdgeVisitor { (@ String currentClass; @) before ClassDef (@ this.currentClass = host.GetName().toString(); @) after Program (@ System.out.println("}"); @) before Part (@ if(Program.theProgram.IsDemeterClass(host.GetClassName().toString())) { System.out.println(" before -> " + this.currentClass + "," + host.GetPartName() + "," + host.GetClassName().toString() + " (@"); System.out.println(" if(this.equal) {"); System.out.println(" Object second = this.history.elementAt(this.history.size() - 1);"); System.out.println(" this.history.addElement(((" + this.currentClass + ")second).get_" + host.GetPartName() + "());"); System.out.println(" }"); System.out.println(" @" + ")"); System.out.println(""); System.out.println(" after -> " + this.currentClass + "," + host.GetPartName() + "," + host.GetClassName().toString() + " (@"); System.out.println(" if(this.equal) {"); System.out.println(" this.history.removeElementAt(this.history.size() - 1);"); System.out.println(" }"); System.out.println(" @" + ")"); System.out.println(""); } @) } GenerateEqualVisitor { (@ void CompareTerminal(String thisClass, String partClass, String partName) { System.out.println(" if(this.equal) {"); System.out.println(" if(host.get_" + partName + "().equals(((" + partClass + ")second).get_" + partName + "())) {"); System.out.println(" this.equal = false;"); System.out.println(" }"); System.out.println(" }"); } String currentClass; @) before Program (@ System.out.println(""); System.out.println(""); System.out.println("EqualVisitor {"); System.out.println(" (@"); System.out.println(" boolean equal = true;"); System.out.println(" Vector history = new Vector();"); System.out.println(""); System.out.println(" void SetSecond(Object second) {"); System.out.println(" this.history = new Vector();"); System.out.println(" this.equal = true;"); System.out.println(""); System.out.println(" this.history.addElement(second);"); System.out.println(" }"); System.out.println(""); System.out.println(" boolean IsEqual() {"); System.out.println(" return this.equal;"); System.out.println(" }"); System.out.println(" @" + ")"); System.out.println(""); @) before ClassDef (@ this.currentClass = host.GetName().toString(); System.out.println(" before " + host.GetName().toString() + " (@"); System.out.println(" Object second = this.history.elementAt(this.history.size() - 1);"); System.out.println(" if(this.equal) {"); System.out.println(" if(second.getClass().toString().compareTo(host.getClass().toString()) != 0) {"); System.out.println(" this.equal = false;"); System.out.println(" }"); @) after ClassDef (@ System.out.println(" }"); System.out.println(" @" + ")"); @) before Part (@ if(!Program.theProgram.IsDemeterClass(host.GetClassName().toString())) { if(Program.theProgram.IsDemeterTerminalClass(host.GetClassName().toString())) { System.out.println(" if(this.equal) {"); System.out.println(" if(!host.get_" + host.GetPartName() + "().equals(((" + this.currentClass + ")second).get_" + host.GetPartName() + "())) {"); System.out.println(" this.equal = false;"); System.out.println(" }"); System.out.println(" }"); } else { // what should we do to compare non-demeter classes? System.err.println(" // came to a part that isn't a demeter class..."); } } @) } // Utility functions // ClassSpec : GetName() -> Ident // ClassDef : GetName() -> Ident // Part : GetName() -> Ident - returns a name if it's in the cd or null // Part : GetPartName() -> String - returns part.GetName() if it exists // or the name demjava will generate if // it doesn't. // Part : GetClassName() -> Ident // Program : IsDemeterClass(String) -> boolean // Program : IsDemeterTerminalClass(String) -> boolean // Program : IsAlternationClass(String) -> boolean /////////// Begin utility code // ClassSpec: GetName() -> Ident ClassSpec { traversal GetCSNameTraversal(GetCSNameVisitor v) { to ClassName; } (@ Ident GetName() { GetCSNameVisitor gnv = new GetCSNameVisitor(); this.GetCSNameTraversal(gnv); return gnv.get_theName(); } @) } GetCSNameVisitor { before ClassName (@ this.set_theName(host.get_name()); @) } // ClassSpec: GetName() -> Ident ClassDef { traversal GetCDNameTraversal(GetCDNameVisitor v) { bypassing { ClassParts, -> *, parameters, * } to ClassName; } (@ Ident GetName() { GetCDNameVisitor gnv = new GetCDNameVisitor(); this.GetCDNameTraversal(gnv); return gnv.get_theName(); } @) } GetCDNameVisitor { before ClassName (@ this.set_theName(host.get_name()); @) } // Part : GetName() -> Ident Part { traversal GetPNameTraversal(GetPNameVisitor v) { to PartName; } (@ Ident GetName() { GetPNameVisitor gnv = new GetPNameVisitor(); this.GetPNameTraversal(gnv); return gnv.get_theName(); } @) } GetPNameVisitor { before PartName (@ this.set_theName(host.get_name()); @) } // returns the name that demjava will generate for this part Part { (@ String GetPartName() { String partName; if(this.GetName() != null) { partName = this.GetName().toString(); } else { partName = this.get_classspec().GetName().toString().toLowerCase(); } return partName; } @) } // Part : GetClassName() -> Ident Part { traversal GetPCNameTraversal(GetPCNameVisitor v) { to ClassName; } (@ Ident GetClassName() { GetPCNameVisitor gnv = new GetPCNameVisitor(); this.GetPCNameTraversal(gnv); return gnv.get_theName(); } @) } GetPCNameVisitor { before ClassName (@ this.set_theName(host.get_name()); @) } // Program : IsDemeterClass(String) -> boolean Program { traversal IsDemeterClassTraversal(IsDemeterClassVisitor v) { bypassing { ClassParts, ClassMethods, -> *, parameters, * } to ClassName; } (@ boolean IsDemeterClass(String className) { IsDemeterClassVisitor idcv = new IsDemeterClassVisitor(); idcv.Init(); idcv.SetTheClass(className); this.IsDemeterClassTraversal(idcv); return idcv.IsIt(); } @) } IsDemeterClassVisitor { (@ String theClass; boolean isIt; void Init() { this.isIt = false; } boolean IsIt() { return this.isIt; } void SetTheClass(String theClass) { this.theClass = theClass; } @) before ClassName (@ if(this.theClass.compareTo(host.get_name().toString()) == 0) { this.isIt = true; } @) } // Program : IsDemeterTerminalClass(String) -> boolean Program { (@ boolean IsDemeterTerminalClass(String className) { if(className.compareTo("Integer") == 0) { return true; } else if(className.compareTo("Ident") == 0) { return true; } else if(className.compareTo("String") == 0) { return true; } else if(className.compareTo("Text") == 0) { return true; } else if(className.compareTo("Boolean") == 0) { return true; } else if(className.compareTo("Float") == 0) { return true; } else if(className.compareTo("Double") == 0) { return true; } else { return false; } } @) } // Program : IsAlternationClass(String) -> boolean Program { traversal IsAlternationClassTraversal(IsAlternationClassVisitor v) { to AlternationClass; } (@ boolean IsAlternationClass(String className) { IsAlternationClassVisitor idcv = new IsAlternationClassVisitor(); idcv.Init(); idcv.SetTheClass(className); this.IsAlternationClassTraversal(idcv); return idcv.IsIt(); } @) } IsAlternationClassVisitor { (@ String theClass; boolean isIt; boolean inAlt; void Init() { this.isIt = false; this.inAlt = false; } boolean IsIt() { return this.isIt; } void SetTheClass(String theClass) { this.theClass = theClass; } @) before AlternationClass (@ this.inAlt = true; @) after ClassDef (@ if(this.inAlt) { if(this.theClass.compareTo(host.GetName().toString()) == 0) { this.isIt = true; } this.inAlt = false; } @) }