//-*-java-*- OutputVisitor { {{ PrintWriter out; Hashtable exclusion_table; // all keys are Strings CoordClassNames current_ccnames; String current_class; // coord info sits here (even in multiclass) boolean current_is_static; // static == "per class" boolean current_is_multiclass; // multiclass => static OutputVisitor(PrintWriter pw) { out = pw; exclusion_table = new Hashtable(); // hash of classes containing hashes of methods; } }} {{boolean first_time_to_coord_dec = true;}} before CoordinatorDeclaration {{ if(first_time_to_coord_dec) first_time_to_coord_dec = false; // else return; // static/multiclass determination current_ccnames = host.get_coordclassnames(); Enumeration ccname_enum = current_ccnames.elements(); current_class = ((ClassName)ccname_enum.nextElement()).get_ident().toString(); if(ccname_enum.hasMoreElements()) current_is_multiclass = true; else current_is_multiclass = false; Granularity gran = host.get_granularity(); if(gran == null) { if(current_is_multiclass) current_is_static = true; else current_is_static = false; } else if(gran instanceof PerClass) { current_is_static = true; } else { // gran instanceof PerObject if(current_is_multiclass) { // per object && multiclass is not allowed Err.err("Coordinator for "+current_ccnames+ " must be declared \"per class\"."); } current_is_static = false; } }} before {VarDeclaration,CondVarDeclaration} {{ Enumeration ccname_enum = current_ccnames.elements(); while(ccname_enum.hasMoreElements()) { Ident class_ident = ((ClassName)ccname_enum.nextElement()).get_ident(); out.print("add: to: "+class_ident+" {\n"); host.toAll(new VarDecVisitor(current_is_static, out)); out.print("}\n\n"); } }} before {SelfexMethodSet,MutexMethodSet} {{ Enumeration excl_enum = host.get_meths().elements(); while(excl_enum.hasMoreElements()) { QualifiedMethodName qmname = (QualifiedMethodName)excl_enum.nextElement(); // check for multiclass ambiguity: if(qmname.get_classname() == null && current_is_multiclass) { Err.err("Methods of exclusion sets in coordinator for "+ current_ccnames+" must be qualified with class names."); return; } String class_name; // current_class is default if(qmname.get_classname() != null) class_name = qmname.get_classname().get_ident().toString(); else { class_name = current_class; qmname.set_classname(ClassName.parse(class_name)); } // allocate necessary hashtables/methexs: String id = qmname.getUniqueId(); if(!exclusion_table.containsKey(class_name)) exclusion_table.put(class_name, new Hashtable()); //new hash of methods Hashtable meth_hash = (Hashtable)exclusion_table.get(class_name); if(!meth_hash.containsKey(id)) meth_hash.put(id, new MethodExclusion(qmname)); MethodExclusion methex = (MethodExclusion)meth_hash.get(id); if((Object)host instanceof SelfexMethodSet) methex.selfex = true; else { Enumeration excl_iter = host.get_meths().elements(); while(excl_iter.hasMoreElements()) methex.mutex.addElement(excl_iter.nextElement()); } } }} public void output() {{ Enumeration class_keys = exclusion_table.keys(); while(class_keys.hasMoreElements()) { Vector seen_cnstrs = new Vector(); String class_name = (String)class_keys.nextElement(); Hashtable meth_hash = (Hashtable)exclusion_table.get(class_name); Enumeration meth_keys = meth_hash.keys(); out.print("add: to: "+class_name+" {\n"); out.print(" private void _done() ("+"@\n"); out.print(" synchronized(cool$synch) { cool$synch.notifyAll(); }\n"); out.print(" @"+")\n"); out.print(" private "); if(current_is_static) out.print("static "); out.print("Object cool$synch = ("+"@ new Object() @"+");\n"); out.print("}\n\n"); while(meth_keys.hasMoreElements()) { String meth_key = (String)meth_keys.nextElement(); MethodExclusion methex = (MethodExclusion)meth_hash.get(meth_key); // output exclusion constructors: out.print("add: to: "+class_name+" {\n"); out.print(" public "); if(current_is_static) out.print("static "); out.print("Cool$Lock "+methex.id+"lock = ("+"@ new Cool$Lock("+methex.selfex+", "); if(methex.mutex.isEmpty()) out.print("null"); else { out.print("new XVector()"); Enumeration mutex_enum = methex.mutex.elements(); while(mutex_enum.hasMoreElements()) { QualifiedMethodName mutex_qmname = (QualifiedMethodName)mutex_enum.nextElement(); String id = mutex_qmname.getUniqueId(); if(seen_cnstrs.contains(id)) out.print(".append("+id+"lock)"); } } seen_cnstrs.addElement(methex.id); out.print(") @"+");\n}\n\n"); // output entry methods; out.print("add: to: "+class_name+" {\n"); out.print(" private void enter_"+methex.id+"() ("+"@\n"); out.print(" while( !(" + (methex.requires==null ? "\n" : (methex.requires.unparse()+" &&\n"))); out.print(" "+methex.id+"lock.isEnterable())) {\n"); out.print(" try {\n"); out.print(" synchronized(cool$synch) { cool$synch.wait(); }\n"); out.print(" }\n"); out.print(" catch(InterruptedException e) {}\n"); out.print(" }\n"); out.print(" " + (methex.on_entry==null ? "" : methex.on_entry.unparse())); out.print("\n @"+")\n}\n\n"); // exclusion/on exit; out.print("before: "+methex.sig+" ("+"@\n"); out.print(" enter_"+meth_key+"();\n@"+")\n"); out.print("after: "+methex.sig+" ("+"@\n"); out.print(" "+ (methex.on_exit==null ? "\n" : methex.on_exit.unparse()+"\n")); out.print(" "+methex.id+"lock.done();\n"); out.print(" _done();\n@"+")\n\n"); } } }} {{ QualifiedMethodNames meth_names; boolean methman_trouble = false; }} before MethodManager {{ meth_names = host.get_meths(); Enumeration methname_enum = meth_names.elements(); while(methname_enum.hasMoreElements()) { QualifiedMethodName qmname = (QualifiedMethodName)methname_enum.nextElement(); if(qmname.get_classname() == null) { if(current_is_multiclass) { Err.err("Classname must be specified in method manager for \"" + qmname + '"'); methman_trouble = true; return; } qmname.set_classname(ClassName.parse(current_class)); } } }} after MethodManager {{ meth_names = null; methman_trouble = false; }} before {MethManPart,Requires} {{ if(methman_trouble) return; Enumeration methname_enum = meth_names.elements(); while(methname_enum.hasMoreElements()) { QualifiedMethodName qmname = (QualifiedMethodName)methname_enum.nextElement(); // qmname should already have classname attached if(!exclusion_table.containsKey(current_class)) exclusion_table.put(current_class, new Hashtable()); // new hash of methods; Hashtable meth_hash = (Hashtable)exclusion_table.get(current_class); String id = qmname.getUniqueId(); if(!meth_hash.containsKey(id)) meth_hash.put(id, new MethodExclusion(qmname)); MethodExclusion methex = (MethodExclusion)meth_hash.get(id); if((Object)host instanceof OnEntry) methex.on_entry = ((OnEntry)(Object)host).get_stmt(); else if((Object)host instanceof OnExit) methex.on_exit = ((OnExit)(Object)host).get_stmt(); else methex.requires = ((Requires)(Object)host).get_exp(); } }} } {CondVarDeclaration,VarDeclaration,VariableDeclarator,CondVarDec} { traversal toAll(VarDecVisitor) { to *; } } VarDecVisitor { {{ private PrintWriter out; private boolean is_static; public VarDecVisitor(boolean cur_is_static, PrintWriter pw) { out = pw; is_static = cur_is_static; } }} before LocVarDecl {{ if(is_static) out.print("static "); }} before CondVarDeclaration {{ if(is_static) out.println("static "); out.print("boolean"); }} after {LocVarDecl,CondVarDeclaration} {{ out.print(";\n"); }} before CFinal {{ out.print("final "); }} around Type {{ StringWriter sw = new StringWriter(); host.universal_trv0(new PrintVisitor(new PrintWriter(sw))); out.print(sw + " "); }} before SquareBrackets {{ out.print("[]"); }} after SquareBracketses {{ out.print(' '); }} around {VariableDeclarators,CondVarDecs} {{ Enumeration dec_enum = host.elements(); boolean first = true; while(dec_enum.hasMoreElements()) { Object dec = dec_enum.nextElement(); if(first) first = false; else out.print(", "); if(dec instanceof VariableDeclarator) ((VariableDeclarator)dec).toAll(this); else ((CondVarDec)dec).toAll(this); } }} before VariableDeclaratorId {{ StringWriter sw = new StringWriter(); host.universal_trv0(new PrintVisitor(new PrintWriter(sw))); out.print(sw + " "); }} around VariableIniter {{ out.print(" = ("+"@ "); StringWriter sw = new StringWriter(); host.universal_trv0(new PrintVisitor(new PrintWriter(sw))); out.print(sw); // ignore this comment out.print(" @"+")"); }} } Requires { public void output(PrintWriter out, Ident clazz, Ident meth) {{ out.print("add: to: "+clazz+" {\n"); out.print(" public Boolean _"+meth+"_req() ("+"@\n"+ " return new Boolean ("+this.get_exp().unparse()+");\n"+ " @"+")\n"); out.print("}\n\n"); }} } OnEntry { public void output(PrintWriter out, Ident clazz, Ident meth) {{ out.print("before: "+clazz+"."+meth+" ("+"@"); out.print(this.get_stmt().unparse()); out.print("@"+")\n\n"); }} } OnExit { public void output(PrintWriter out, Ident clazz, Ident meth) {{ out.print("after "+clazz+"."+meth+" ("+"@"); out.print(this.get_stmt().unparse()); out.print("@"+")\n\n"); }} } QualifiedMethodName { public String getUniqueId() to {MethodName,Type} { {{ StringBuffer ret = new StringBuffer(); }} before MethodName {{ ret.append("meth$" + host.get_ident().toString()); }} before MethodArgTypes {{ ret.append('$'); }} before Type {{ TypeAlt typealt = host.get_typealt(); if(typealt instanceof PrimitiveType) ret.append((PrimitiveType)typealt + "$"); else ret.append(((TName)typealt).realType() + "$"); short num_bracks = 0; Enumeration brack_enum = host.get_bracks().elements(); while(brack_enum.hasMoreElements()) { brack_enum.nextElement(); num_bracks++; } if(num_bracks > 0) { ret.append(num_bracks); ret.append('$'); } }} return {{ ret.toString() }} } public String toString() {{ StringWriter sw = new StringWriter(); universal_trv0(new PrintVisitor(new PrintWriter(sw))); return sw.toString(); }} } MethManPart { {{ public abstract void output(PrintWriter out, Ident clazz, Ident meth); }} } TName { String realType() {{ Enumeration enum = get_name().elements(); Ident type = null; while(enum.hasMoreElements()) type = (Ident)enum.nextElement(); return type.toString(); }} } ClassName { public String toString() {{ return get_ident().toString(); }} } CoordClassNames { public String toString() to ClassName { {{ StringBuffer ret = new StringBuffer("{"); boolean first = true; }} before ClassName {{ if(first) first = false; else ret.append(","); ret.append(host); }} finish {{ ret.append("}"); }} return {{ ret.toString() }} } }