utils.beh.html

Program{
	(@
    private static Hashtable checksums;
    private static File output, old;
    private static Vector javaFiles = new Vector();
    private static Checksum ck;
  @)
	static void readChecksums(File file)(@
    try {
      checksums = (Hashtable)
	(new ObjectInputStream(new FileInputStream(file))).readObject();
    } catch (IOException e) {
      checksums = new Hashtable();
    } catch (ClassNotFoundException e) {
      throw new RuntimeException(e.toString());
    }
  @)
	static void writeChecksums(File file)(@
    try {
      (new ObjectOutputStream(new FileOutputStream(file)))
      .writeObject(checksums);
    } catch (IOException e) {
      throw new RuntimeException(e.toString());
    }
  @)
	static void openOutputFile(File file)(@
    output = file;
    old = new File(output + "~");
    if (output.exists()) output.renameTo(old);
    try {
      ck = new /* CRC32 */ Adler32();
      out = new PrintWriter
	      (new CheckedOutputStream(new FileOutputStream(output), ck));
    } catch (IOException e) {
      throw new RuntimeException(e.toString());
    }
  @)
	static void closeOutputFile()(@
    out.flush();
    out.close();
    if (old.exists()) {
      Long oldck = (Long) checksums.get(output);
      if (oldck != null && oldck.longValue() == ck.getValue()) {
	old.renameTo(output);
      } else {
	checksums.put(output, new Long(ck.getValue()));
	old.delete();
      }
    }
  @)
	static void openJavaOutputFile(ClassName c)(@
    File f = new File(gendir, c + ".java");
    openOutputFile(f);
    javaFiles.addElement(f);
  @)
	static void closeJavaOutputFile()(@
    closeOutputFile();
  @)
}

Program{
	traversal toAll(UniversalVisitor v) {
		bypassing{ Hashtable }to*;
	}
}

ClassNameAccessor{
	before ClassSpec (@ @)
	before ClassName (@ @)
}

ClassDef{
	traversal toClassName(ClassNameAccessor v) {
		bypassing{ ClassParts, ClassMethods, -> *, parameters, * }to ClassName;
	}
}

{ Subclass, Superclass, Part, RepeatedPart }{
	traversal toClassName(ClassNameAccessor v) {
		bypassing{ -> *, actual_parameters, * }to ClassName;
	}
}

{ ClassDef, Subclass, Superclass, Part, RepeatedPart }{
	ClassName get_classname()=toClassName{
		before ClassName (@ return_val = host; @)
	}
}

{ ClassDef, Part, RepeatedPart }{
	void set_classname(ClassName classname)=toClassName{
		before ClassSpec (@ host.set_classname(classname); @)
	}
}

ClassDef{
	ClassName_Commalist get_parameters()via ParamClassName to ClassName_Commalist{
		before ClassName_Commalist (@ return_val = host; @)
	}
}

{ Program, ClassGraph }{
	traversal allClassDefs(ClassDefVisitor v) {
		to ClassDef;
	}
}

ClassDefVisitor{
	before{ ClassGraph, ClassDef }(@ @)
	after{ ClassGraph }(@ @)
}

Program{
	(@
    void buildClassDefTable() { cg.buildClassDefTable(); }
    ClassDef findClassDef(ClassName name) { return cg.findClassDef(name); }
    boolean definesClass(ClassName name) { return cg.definesClass(name); }
    void addClassDef(ClassDef def) { cg.addClassDef(def); }
  @)
}

ClassGraph{
	init (@
    defdict = new Hashtable();
    classes = new ClassGraphEntry_DList();
  @)
	void buildClassDefTable()=allClassDefs{
		(@ Hashtable defdict; @)
		before ClassGraph (@ defdict = new Hashtable(); @)
		before ClassDef (@ defdict.put(host.get_classname(), host); @)
		after ClassGraph (@ host.set_defdict(defdict); @)
	}
	ClassDef findClassDef(ClassName name)(@
    return (ClassDef) defdict.get(name);
  @)
	boolean definesClass(ClassName name)(@
    return findClassDef(name) != null;
  @)
	void addClassDef(ClassDef def)(@
    classes.addElement(def);
    defdict.put(def.get_classname(), def);
  @)
}

ClassDef{
	ClassName getPartClass(PartName name)(@
    Part thePart = getPartFromPartName(name);
    return (thePart == null ? null : thePart.get_classname());
  @)
	Part getPartFromPartName(PartName name)via{ ConstructionClass, AlternationClass }to PartName{
		(@ boolean isPart; @)
		before PartName (@ isPart = host.equals(name); @)
		after Part (@ if (isPart) return_val = host; @)
	}
}

Part{
	(@
    boolean isTerminal() {
      ClassDef def = Program.prog.findClassDef(get_classname());
      return def == null || def.isInterface();
    }
    String makeWrapper(ClassName source, String body) {
      return new PartGlob(source, get_partname(), get_classname())
	     + " " + Text.begin + body + Text.end;
    }
    String makeBefore(ClassName source, String body) {
      return "  before " + makeWrapper(source, "\n" + body + "  ");
    }
    String makeAfter(ClassName source, String body) {
      return "  after " + makeWrapper(source, "\n" + body + "  ");
    }
  @)
}

ClassName{
	(@
    String makeWrapper(String body) {
      return this + " " + Text.begin + body + Text.end;
    }
    String makeBefore(String body) {
      return "  before " + makeWrapper("\n" + body + "  ");
    }
    String makeAfter(String body) {
      return "  after " + makeWrapper("\n" + body + "  ");
    }
  @)
}

ClassName{
	(@
    private static String builtinTypes[] = {
      "boolean", "char", "byte", "short", "int", "long", "float", "double"
    };
    private static String terminalClasses[] = {
      // from java.lang.*:
      "Boolean", "Character", "Integer", "Long", "Float", "Double",
      "Number", "String", "StringBuffer",
      // from demeter.*:
      "Ident", "Text"
    };
    boolean isBuiltinType() {
      String s = toString();
      for (int i = 0; i < builtinTypes.length; i++) {
	if (builtinTypes[i].equals(s)) return true;
      }
      return false;
    }
    boolean isTerminalClass() {
      String s = toString();
      for (int i = 0; i < terminalClasses.length; i++) {
	if (terminalClasses[i].equals(s)) return true;
      }
      return false;
    }
    boolean isKnownTerminal() {
      return isBuiltinType() || isTerminalClass();
    }
  @)
}

{ Program, ClassDef }{
	traversal allParts(PartVisitor v) {
		to{ Part, RepeatedPart };
	}
}

PartVisitor{
	before{ Program, ClassDef, Part, RepeatedPart }(@ @)
	around ClassDef (@ subtraversal.apply(); @)
	after{ Program, ClassDef, Part, RepeatedPart }(@ @)
}

ClassDef{
	void addMethod(String signature, String body)(@
    String method = signature + " {";
    if (body.indexOf('\n') != -1) method += "\n";
    method += body + "  }\n";
    addMethod(method);
  @)
	void addMethod(StringBuffer method_text)(@
    addMethod(method_text.toString());
  @)
	void addMethod(String method_text)(@
    addMethod(new Verbatim(new JavaCode(new Text(method_text))));
  @)
	void addMethod(Method method)to-stop Method_SList{
		before ClassDef (@
      if (host.get_classmethods() == null)
	host.set_classmethods(new ClassMethods());
    @)
		before ClassMethods (@
      if (host.get_methods() == null)
	host.set_methods(new Method_SList());
    @)
		before Method_SList (@ host.addElement(method); @)
	}
}

ClassDef{
	boolean hasNoArgConstructor()to Constructor{
		before Constructor (@ return_val = true; @)
	}
}

{ Program, ClassDef }{
	traversal allEdges(EdgeVisitor v) {
		to{ Part, Subclass, Superclass };
	}
}

EdgeVisitor{
	before Program (@ @)
	around ClassDef (@ subtraversal.apply(); @)
	before{ Part, Subclass, Superclass }(@ @)
	before{ ClassGraph, ConstOrAltClass, ConstructionClass, AlternationClass, ClassParents, OptionalPart, ClassDef }(@ @)
	after{ Part, Subclass, Superclass, ConstructionClass, ClassDef, OptionalPart }(@ @)
}

TraversalParms{
	traversal allVisitorNames(VisitorNameVisitor v) {
		to VisitorName;
	}
}

VisitorNameVisitor{
	before{ Visitor, VisitorName }(@ @)
	after Visitor (@ @)
}

ClassDef{
	boolean isConstructionClass()(@ return getClassType().get_is_con(); @)
	boolean isAlternationClass()(@ return getClassType().get_is_alt(); @)
	boolean isRepetitionClass()(@ return getClassType().get_is_rep(); @)
	boolean isPublic()(@ return getClassType().get_is_public(); @)
	boolean isFinal()(@ return getClassType().get_is_final(); @)
	boolean isInterface()(@ return getClassType().get_is_interface(); @)
	boolean isNotParsed()(@ return getClassType().get_is_not_parsed();@)
	boolean isVisitor()(@ return getClassType().get_is_visitor(); @)
	ClassType getClassType()to{ ConstructionClass, AlternationClass, RepetitionClass, PublicClass, FinalClass, InterfaceClass, VisitorClass, NotParsedClass }{
		init (@ return_val = new ClassType(); @)
		before ConstructionClass (@ return_val.set_is_con(true); @)
		before AlternationClass (@ return_val.set_is_alt(true); @)
		before RepetitionClass (@ return_val.set_is_rep(true); @)
		before PublicClass (@ return_val.set_is_public(true); @)
		before FinalClass (@ return_val.set_is_final(true); @)
		before InterfaceClass (@ return_val.set_is_interface(true); @)
		before VisitorClass (@ return_val.set_is_visitor(true); @)
		before NotParsedClass (@ return_val.set_is_not_parsed(true); @)
	}
	void markVisitor()(@ keywords.addElement(new VisitorClass()); @)
	void markNotParsed()(@ keywords.addElement(new NotParsedClass()); @)
}

Part{
	boolean isFinal()(@ return getPartType().get_is_final();	@)
	boolean isStatic()(@ return getPartType().get_is_static();	@)
	boolean isDerived()(@ return getPartType().get_is_derived();	@)
	boolean hasGetter()(@ return getPartType().get_has_getter(); @)
	boolean hasSetter()(@ return getPartType().get_has_setter(); @)
	PartType getPartType()to{ FinalPart, StaticPart, ReadOnlyPart, PrivatePart, DerivedPart }{
		init (@
      return_val = new PartType();
      return_val.set_has_getter(true);
      return_val.set_has_setter(true);
    @)
		before FinalPart (@
      return_val.set_is_final(true);
      return_val.set_has_setter(false);
    @)
		before StaticPart (@
      return_val.set_is_static(true);
    @)
		before PrivatePart (@
      return_val.set_has_getter(false);
      return_val.set_has_setter(false);
    @)
		before ReadOnlyPart (@
      return_val.set_has_setter(false);
    @)
		before DerivedPart (@
      return_val.set_is_derived(true);
    @)
	}
	void markDerived()(@ keywords.addElement(new DerivedPart()); @)
}

JavaType{
	boolean isVoid()(@ return toString().equals("void"); @)
}

ClassName{
	(@
    boolean isA(ClassName ancestor) {
      if (this.equals(ancestor)) return true;
      ClassDef def = Program.prog.findClassDef(this);
      if (def != null) {
        ClassName sup = def.get_superclass_name();
        if (sup != null) return sup.isA(ancestor);
      }
      return false;
    }
  @)
}

ClassDef{
	ClassDef get_superclass_def()(@
    ClassName super_name = get_superclass_name();
    return super_name == null ? null : Program.prog.findClassDef(super_name);
  @)
	ClassName get_superclass_name()via Superclass to ClassName{
		before ClassName (@ return_val = host; @)
	}
}

{ PackageName, Name }{
	public String toString()(@ return first.toString(); @)
}

{ Nonempty_PackageName, Nonempty_Name }{
	public String toString()(@
    return it + (next == null ? "" : "." + next);
  @)
}

{ ClassName, PartName, TraversalName, VisitorName, MethodName, ParmName, StrategyName }{
	public String toString()(@ return name.toString(); @)
}

TraversalMethodName{
	public String toString()(@ return methodname.toString(); @)
}

{ Subclass, Superclass, Interface }{
	public String toString()(@ return classspec.toString(); @)
}

ClassSpec{
	public String toString()(@ return classname.toString(); @)
}

VisitorSpec{
	public String toString()(@ return methods.toString(); @)
}

JavaType{
	public String toString()(@ return type.toString(); @)
}

JavaCode{
	public String toString()(@ return Text.begin + code + Text.end; @)
}

PlainSyntax{
	public String toString()(@ return "\"" + string + "\""; @)
}

PrintIndent{
	public String toString()(@ return "+"; @)
}

PrintUnindent{
	public String toString()(@ return "-"; @)
}

PrintSkip{
	public String toString()(@ return "*l"; @)
}

PrintSpace{
	public String toString()(@ return "*s"; @)
}

LocalLookahead{
	public String toString()(@ return "*lookahead* "+javacode; @)
}

{ ClassName_Commalist, Superclass_Commalist, Interface_Commalist, Glob_Commalist, ClassGlob_Commalist, Visitor_Commalist }{
	public String toString()(@
    return (first == null ? "" : first.toString());
  @)
}

{ Nonempty_ClassName_Commalist, Nonempty_Interface_Commalist, Nonempty_Superclass_Commalist, Nonempty_Glob_Commalist, Nonempty_ClassGlob_Commalist, Nonempty_Visitor_Commalist }{
	public String toString()(@
    return it + (next == null ? "" : ", " + next);
  @)
}

{ ClassGlobSet, GlobSet }{
	public String toString()(@
    return "{ " + (globs == null ? "" : globs.toString()) + " }";
  @)
}

OneClassGlob{
	public String toString()(@ return classglob.toString(); @)
}

ClassNameExact{
	public String toString()(@ return classname.toString(); @)
}

PartNameExact{
	public String toString()(@ return partname.toString();  @)
}

{ AnyClass, AnyPart }{
	public String toString()(@ return "*";           @)
}

TraversalParms{
	public String toString()(@ return "(" + visitors + ")"; @)
}

TraversalRef{
	public String toString()(@ return (equals == null ? "" : "= ") + name; @)
}

Visitor{
	public String toString()(@ return classname + " " + visitorname; @)
}

ParenVisitorRef{
	public String toString()(@ return "(" + visitorClasses + ");"; @)
}

WithVisitorRef{
	public String toString()(@ return "with " + visitorClasses + ";"; @)
}

{ ClassGlob, SourceGlob, DestGlob }{
	public String toString()(@ return name.toString(); @)
}

PartGlob{
	public String toString()(@
      return "-> " + source + ", " + name + ", " + dest;
  @)
}

SubclassGlob{
	public String toString()(@ return "=> " + source + ", " + dest; @)
}

SuperclassGlob{
	public String toString()(@ return ":> " + source + ", " + dest; @)
}

Before{
	public String toString()(@ return "before"; @)
}

Around{
	public String toString()(@ return "around"; @)
}

After{
	public String toString()(@ return "after";  @)
}

ClassMethods{
	public String toString()(@
    return "{\n" + (methods == null ? "" : methods.toString()) + "\n}";
  @)
}

{ Package, Import, Method_SList, StrategyExpression, StrategyGraph, MethodSignature }{
	(@
    public String toString() {
      StringWriter w = new StringWriter();
      toAll(new PrintVisitor(new PrintWriter(w)));
      return w.toString();
    }
  @)
}

{ Package, Import, Method_SList, StrategyExpression, StrategyGraph, MethodSignature }{
	traversal toAll(UniversalVisitor v) {
		bypassing{ Vector, Hashtable }to*;
	}
}

{ ClassName, PartName, TraversalName, Glob, WrapperKind, Superclass }{
	(@
    public boolean equals(Object obj) {
      return toString().equals(obj.toString());
/*
      EqualVisitor eq = new EqualVisitor(obj);
      toAll(eq);
      // universal_trv0(eq);
      return eq.get_is_equal();
*/
    }
  @)
}

ClassDef{
	(@
    ClassDef deepCopy() {
      CopyVisitor c = new CopyVisitor(getClass());
      toAll(c);
      // universal_trv0(c);
      return (ClassDef) c.get_copy();
    }
  @)
	traversal toAll(UniversalVisitor v) {
		bypassing ClassMethods to*;
	}
}

ClassMethods{
	ClassMethods deepCopy()(@
    CopyVisitor c = new CopyVisitor(getClass());
    toAll(c);
    return (ClassMethods) c.get_copy();
  @)
	traversal toAll(UniversalVisitor v) {
		bypassing Hashtable to*;
	}
}

{ PackageName, ClassName, PartName, TraversalName, VisitorName, MethodName, StrategyName, Glob, WrapperKind }{
	(@ public int hashCode() { return toString().hashCode(); } @)
}

ClassName_Commalist{
	(@
    /** The index of name in the list, or -1 if it's not in the list. */
    public int indexOf(ClassName name) {
      Enumeration e = elements();
      int i = 0;
      while (e.hasMoreElements()) {
	if (((ClassName) e.nextElement()).equals(name)) return i;
	i++;
      }
      return -1;
    }
  @)
}

ClassSpec_Commalist{
	(@
    /** The ith element in the list, or null if the list isn't that long. */
    public ClassSpec elementAt(int i) {
      Enumeration e = elements();
      while (e.hasMoreElements()) {
	ClassSpec spec = (ClassSpec) e.nextElement();
	if (i == 0) return spec;
	i--;
      }
      return null;
    }
  @)
}

TraversalParms{
	int size()(@ return visitors == null ? 0 : visitors.size(); @)
	Enumeration elements()(@
    Visitor_Commalist l = 
      (visitors == null ? new Visitor_Commalist() : visitors);
    return l.elements();
  @)
	TraversalParms reverse()(@
    Visitor_Commalist revvis = null;
    Enumeration e = elements();
    if (e.hasMoreElements()) {
      revvis = new Visitor_Commalist();
      while (e.hasMoreElements()) {
	Visitor v = (Visitor) e.nextElement();
	revvis.push(v);
      }
    }
    return new TraversalParms(revvis);
  @)
}