// gencode.beh -- Code generation // $Id: gencode.beh,v 1.10 2001/10/07 06:57:41 dougo Exp $ Program { (@ static final String common_imports = "import edu.neu.ccs.demeter.*;"; @) /** Generate Java code or core aspect. Return vector of aspect files. */ private Vector generateCode(boolean is_aspect) to { GlobalImports, PackageDirective, ClassDef } { start (@ return_val = new Vector(); @) (@ GlobalImports imports; PackageDirective pkg; @) before GlobalImports (@ imports = host; @) before PackageDirective (@ pkg = host; @) before ClassDef (@ ClassName c = host.get_classname(); if (is_aspect) { File aspectfile = new File(Program.prog.gendir, c + ".wvr"); return_val.addElement(aspectfile); Program.openOutputFile(aspectfile); Program.out.println("core:"); } else { Program.openJavaOutputFile(c); } // Generate the header, with the global imports and the most // recent package declaration & local imports. if (pkg != null) Program.out.println(pkg); Program.out.println(imports); Program.out.println(Program.common_imports); if (is_aspect) { Program.out.print("add: "); } host.printKeywords(); Program.out.print(c); host.printParents(); Program.out.println(" {"); if (!host.isInterface()) { host.generateStructureCode(is_aspect); host.generateConstructors(is_aspect); host.generateUtilCode(is_aspect); } host.generateBehaviorCode(is_aspect); Program.out.println("}"); if (is_aspect) { Program.closeOutputFile(); } else { Program.closeJavaOutputFile(); } @) } } ClassDef { void printKeywords() to { PublicClass, FinalClass, AlternationClass, InterfaceClass } { (@ String cl = "class "; @) before PublicClass (@ Program.out.print("public "); @) before FinalClass (@ Program.out.print("final "); @) before AlternationClass (@ Program.out.print("abstract "); @) before InterfaceClass (@ cl = "interface "; @) after ClassDef (@ Program.out.print(cl); @) } } ClassDef { void printParents() to { Superclass_Commalist, Interface_Commalist } { before Superclass_Commalist {{ Program.out.print(" extends " + host); }} before Interface_Commalist {{ Program.out.print(" implements " + host); }} } } ClassDef { void generateStructureCode(boolean is_aspect) = allParts { before Part (@ host.print(is_aspect); @) } } Part { void print(boolean is_aspect) (@ if (!isDerived()) { PartName part = get_partname(); ClassName type = get_classname(); Program.out.print(" protected "); printKeywords(); Program.out.print(type + " " + part); if (partinit != null) { Program.out.print(" =" + (is_aspect ? " " + partinit.get_javacode() : "" + partinit.get_javacode().get_code()) + ";"); } else { Program.out.println(";"); } // For now, make getter and setter package-scope instead of // omitting them. String open = (is_aspect ? Text.begin : "{"); String close = (is_aspect ? Text.end : "}"); Program.out.print(" "); if (hasGetter()) Program.out.print("public "); printKeywords(); Program.out.println(type + " get_" + part + "()" + " " + open + " return " + part + "; " + close); if (!isFinal()) { Program.out.print(" "); if (hasSetter()) Program.out.print("public "); printKeywords(); Program.out.println("void" + " set_" + part + "(" + type + " new_" + part + ")"); Program.out.println(" " + open + " " + part + " = new_" + part + "; " + close); } } @) void printKeywords() to { FinalPart, StaticPart } { before FinalPart (@ Program.out.print("final "); @) before StaticPart (@ Program.out.print("static "); @) } } Parts { public Parts lisp_append(Parts list) (@ Parts retval = new Parts(); Enumeration e = this.elements(); while (e.hasMoreElements()) retval.addElement((Part) e.nextElement()); e = list.elements(); while (e.hasMoreElements()) retval.addElement((Part) e.nextElement()); return retval; @) } ClassDef { void generateConstructors(boolean is_aspect) (@ String open = (is_aspect ? Text.begin : "{"); String close = (is_aspect ? Text.end : "}"); Parts parts = getParts(); Parts superclassParts = getSuperclassParts(); Parts allParts = superclassParts.lisp_append(parts); boolean hasParts = !allParts.isEmpty(); boolean hasNoArgConstructor = hasNoArgConstructor(); if (hasParts && !hasNoArgConstructor) { // no-arg constructor, can be called from same package only. // This is needed for, e.g., the parse functions. Program.out.print(" "); // johan was here for jtsillas Program.out.print("public "); // johan left if (is_aspect) Program.out.print("constructor "); Program.out.println(get_classname() + "() " + open + " super(); " + close); } if (hasParts || !hasNoArgConstructor) { Program.out.print(" public "); if (is_aspect) Program.out.print("constructor "); Program.out.print(get_classname() + "("); allParts.generateConstructorArgs(); Program.out.println(") " + open); Program.out.print(" super("); superclassParts.generateConstructorSuperInit(); Program.out.println(");"); parts.generateConstructorInits(); Program.out.println(" " + close); } @) private Parts getParts() = allParts { init (@ return_val = new Parts(); @) before Part (@ if (!host.isFinal() && !host.isStatic() && !host.isDerived()) return_val.addElement(host); @) } private Parts getSuperclassParts() (@ ClassDef superclass = get_superclass_def(); // A class might extend an external class, so the superclass might // not have a definition. if (superclass != null) { return superclass.getSuperclassParts() .lisp_append(superclass.getParts()); } return new Parts(); @) } Parts { void generateConstructorArgs() (@ boolean first = true; Enumeration e = elements(); while (e.hasMoreElements()) { Part part = (Part) e.nextElement(); if (first) first = false; else Program.out.print(", "); Program.out.print(part.get_classname() + " " + part.get_partname()); } @) void generateConstructorSuperInit() (@ boolean first = true; Enumeration e = elements(); while (e.hasMoreElements()) { Part part = (Part) e.nextElement(); if (first) first = false; else Program.out.print(", "); Program.out.print(part.get_partname()); } @) void generateConstructorInits() (@ Enumeration e = elements(); while (e.hasMoreElements()) { PartName part = ((Part) e.nextElement()).get_partname(); Program.out.println(" set_" + part + "(" + part + ");"); } @) } ClassDef { void generateUtilCode(boolean is_aspect) (@ generateParseCode(is_aspect); @) } ClassDef { void generateBehaviorCode(boolean is_aspect) // via Method bypassing VisitorSpec bypassing VisitorSpec via { MethodDef, Wrapper, Getter, Setter, Constructor, Start, Finish, ReturnValue, Verbatim } to { JavaCode, NoMethodBody } { (@ String open, close; @) (@ ClassDef classdef; ClassName classname; @) before ClassDef (@ open = (is_aspect ? Text.begin : "{"); close = (is_aspect ? Text.end : "}"); classdef = host; classname = host.get_classname(); @) (@ HostSpec hosts; @) before Method (@ hosts = null; @) before MethodDef (@ Program.out.print(" " + host.get_methodsignature()); @) before NoMethodBody (@ Program.out.println(";"); @) before VerbatimMethodBody (@ Program.out.print(" " + open); @) (@ WrapperKind kind; @) before Wrapper (@ hosts = host.get_hosts(); kind = host.get_kind(); @) (@ PartName partname; ClassName partclassname; @) before Accessor (@ partname = host.get_partname(); partclassname = classdef.getPartClass(partname); @) before Getter (@ Program.out.print(" public " + partclassname + " get_" + partname + "() " + open); @) before Setter (@ Program.out.print(" public void set_" +partname+ "(" + partclassname + " dest) " + open); @) before Constructor (@ Program.out.print(" public " + (is_aspect ? "constructor " : "") + classname + "() " + open); @) before Start (@ Program.out.print(" public void start() " + open); @) before Finish (@ Program.out.print(" public void finish() " + open); @) before ReturnValue (@ Program.out.print(" " +host.get_type()+ " get_return_val() " + open + " return"); @) before Verbatim (@ if (is_aspect) Program.out.print(Text.begin); @) before JavaCode (@ if (hosts != null) { hosts.generateWrapperCode(kind, host.get_code(), is_aspect); } else { Program.out.print(host.get_code()); } @) after { VerbatimMethodBody, Accessor, Constructor, Start, Finish } (@ Program.out.println(close); @) after ReturnValue (@ Program.out.println("; " + close); @) after Verbatim (@ if (is_aspect) Program.out.println(Text.end); @) } }