RIDL { public void makeridl(edu.neu.ccs.demeter.tools.generate.Program prog, java.util.Vector weaverfiles) to * { // This is the heart of the system- the RIDL visitor (@ String ms = null; String cn = null; String main_params = null; String main_pargs = null; // String p_params = null; always same as main String p_body = " //p_body\n"; String p_ppargs = null; String pp_body = " //pp_body\n"; String pp_realargs = null; String interfacemeths = ""; java.io.PrintWriter outstr; java.io.FileOutputStream outfilestr; java.io.File outfile; Args args; @) // A method on the visitor! (@ void out(String output) {outstr.println(output); } @) (@ String comma(String foo) {return (foo.equals(""))?foo:(foo+", "); } @) before FileMarker (@ // close any open files, open new files.. try { if (outfile != null) { outstr.flush(); outfilestr.close(); weaverfiles.addElement(outfile); } outfile = new File(Options.outputdir,host.get_filename()+".wvr"); System.err.println(" writing "+outfile.getName()); outfilestr = new java.io.FileOutputStream(outfile); outstr = new java.io.PrintWriter(outfilestr); // the first line of the new file: out("ridl: \nimport edu.neu.ccs.demeter.*;"); } catch (Exception e) { e.printStackTrace(); System.exit(1); } @) finish (@ try { if (outfile != null) { outstr.flush(); outfilestr.close(); weaverfiles.addElement(outfile); } } catch (Exception e) { e.printStackTrace(); System.exit(1); } @) before Portal (@ interfacemeths =""; cn = host.get_classname().toString(); out(" implement: RIDL_Runtime.RIDL_Object in: "+cn+";"); out(" implement: java.io.Serializable in: "+cn+";"); // only on the one that inherits from Object out("add: to: "+cn+" {\n "); if (RIDL.find_closest_superportal(host.get_classname(), prog)== null) { out(" "+Text.begin+" "+cn+"P _proxy; "+Text.end+"\n"); // we want the proxy holder. out(" public RIDL_Runtime.RIDL_ObjectP _get_p() "+Text.begin+ " return (RIDL_Runtime.RIDL_ObjectP) _proxy;"+Text.end+"\n"); out(" public void _set_p(RIDL_Runtime.RIDL_ObjectP p) "+Text.begin+ " _proxy= ("+cn+"P) p;"+Text.end+"\n"); } // only on concrete classes if (prog .public_findClassDef(edu.neu.ccs.demeter.tools.generate.ClassName.parse(cn.toString())) .public_isConcreteClass()) out(" public static RIDL_Runtime.RIDL_Object remotenew(String host, int port) "+Text.begin+"\n"+ " // create a new instance on a host:port\n"+ " // eventually, this will be done in a faster way, I think\n"+ " return RIDL_Runtime.RIDL_RemoteInst.remotenew(\""+cn+"\",host,port); \n"+ Text.end); out(" public RIDL_Runtime.RIDL_Object _make_fake() "+Text.begin+"\n"+ " "+cn+"PP_I gref = null;\n"+ " if (_proxy!=null) \n"+ " // ok so this IS already a fake (it has a proxy), so just return us\n"+ " return (RIDL_Object) this;\n"+ " else { \n"+ " // this is the real object, so we make a fake\n"+ " try {\n"+ " gref = new "+cn+"PP((RIDL_Runtime.RIDL_Object)this);}\n"+ " RIDL_Runtime.RIDL_Object fake = (RIDL_Runtime.RIDL_Object) this.getClass().newInstance();\n"+ " fake._set_p(new "+cn+"P()); \n"+ " fake._get_p()._set_pp(gref);\n"+ " return fake;\n"+ " } catch (InstantiationException e) { e.printStackTrace(); return null; } \n"+ " catch (IllegalAccessException e) { e.printStackTrace(); return null; } \n"+ " catch (java.rmi.RemoteException e) {e.printStackTrace(); return null;} \n"+ " "+Text.end+"\n"); out("}\n\n"); out("add: public class "+cn+"P extends "+host.extendstoStringP()+" {\n"+ " public constructor "+cn+"P(java.rmi.Remote pp) "+ Text.begin+" _pp = pp;"+Text.end+"\n"+ " public constructor "+cn+"P() "+ Text.begin+" "+Text.end+"\n"+ "}"); out("add: public class "+cn+"PP extends "+host.extendstoStringPP()+ " implements "+cn+"PP_I {\n"+ " public constructor "+cn+"PP(RIDL_Runtime.RIDL_Object real) throws java.rmi.RemoteException "+ Text.begin+" super(real); "+Text.end+"\n"+ "}"); @) after Portal (@ out("add: interface "+cn+"PP_I extends java.rmi.Remote {\n"+ interfacemeths+"}\n"); @) before Method (@ RIDL.dbg("method: "+host.toString()); String mn = host.get_name().toString(); args = host.get_args(); out(" rename: "+cn+"."+mn+" to: "+mn+"_hidden ;"); out(" // ignoring access modifiers... \n"); // overwriting anything that may be there already // the "" is important- it is assumed by comma() main_params = ""; main_pargs = ""; p_body = " //p_body\n"; p_ppargs = ""; pp_body = " //pp_body\n"; pp_realargs = ""; @) before MethodParm (@ RIDL.dbg("method parm: "+host.toString()); /* make some nice code to package up the params as they ought to be 1) verify that host.JavaType has a portal. 2) over-ride the default transfer mode with the one attached to the host, if any 3) case transfermode: BYCOPY: in P A) make a new var ArgType argname_copy = pruned copy of argname B) add argname_copy to args to remote obj in PP C) add ArgType argname to paramlist D) nothing E) add argname to args to real obj BYGREF: in P A) make a new var ArgTypePP argname_gref = new ArgTypePP argname_gref._set_real(argname); B) add argname_gref to args to remote obj in PP C) add ArgTypePP argnamepp to paramlist D) make variable ArgType argname = new ArgName(); ArgTypeP argnamep = new ArgNameP(); argname._set_p(argnamep); argnamep._set_pp(argnamepp); E) add argname to args to real obj similar actions for the return case */ // step 2 TransferMode tm = args.findTransferMode(host.get_name().toString(),host.get_type()); // step 3 /* this is the main hotspot: Assume we are in class Foo and calling a method bar with arg baz. */ JavaType baztype = host.get_type(); String bazname = host.get_name().toString(); String baznameprim = bazname+"_prim"; // I) we need to add baz to the args passed to FooP::bar main_params = comma(main_params)+host.toSigStr(""); // and likewise, FooP::bar needs to expect a baz main_pargs = comma(main_pargs) +host.toArgStr(); // II) FooP::bar needs to pack baz, and FooPP::bar needs to unpack it: String baz_pack = tm.make_pack_var(baztype,bazname,baznameprim); String baz_unpack = tm.make_unpack_var(baztype,bazname,baznameprim); p_body = p_body + baz_pack +"\n"; pp_body = pp_body + baz_unpack +"\n"; // now we need to add bazprim to the params to FooPP::bar p_ppargs = comma(p_ppargs)+baznameprim; // and also from FooPP:bar to Foo::bar (on the remote machine) pp_realargs = comma(pp_realargs)+baznameprim; @) after MethodSignature (@ RIDL.dbg("method sig: "+host.toString()); interfacemeths = interfacemeths+host.toIntSigStr("_PP",args)+ " throws java.rmi.RemoteException; \n"; // IntSigStr appends P to objects passed by gref /* on a per-argument basis: main_params main_pargs p_body becomes the body of FooP.meth() p_ppargs becomes args passed to FooPP.meth() from FooP.meth() - no parens pp_body and body pp_realargs params passed to Foo from FooPP no parens */ JavaType rettype = host.get_returntype(); // Foo.meth out(" add: to: "+cn+" { "+host.toSigStr("")); out(" "+Text.begin); out(" "+rettype.createvar("_retval")); // it would probably be better to just catch a NullPointer if it wasn't a local proxy" out(" if (_proxy != null) {"); out(" "+rettype.assignvar("_retval","(("+cn+"P)_proxy)."+host.get_name()+"_P("+main_pargs+")")+";"); out(" } else {"); out(" "+rettype.assignvar("_retval",host.get_name()+"_hidden("+main_pargs+")")+";"); out(" }"); out(" "+rettype.returnvar("_retval")); out(" "+Text.end+" }"); /* We need to do some work with any return value. if it is void, do nothing if it is an object type, FooPP needs to pass the proxy, so the return type is old+"P" FooP needs to make a real object out of what FooPP returns if it is a primitive, we're fine */ TransferMode tm = args.findTransferMode("return",host.get_returntype()); JavaType ptype = host.get_returntype(); JavaType pptype = tm.what_packed_type(ptype); // FooP.meth out(" add: to: "+cn+"P { "+host.toSigStr("_P")); out(" "+Text.begin); out(" "+tm.p_makeretvar(host,"_retval")); out(" try {"); out(p_body); out(" // THE CALL"); out(" "+tm.p_makecallpp(host,"_retval","(("+cn+"PP_I) _pp)."+host.get_name()+"_PP("+p_ppargs+")")+";"); out(" } catch (java.rmi.RemoteException e) {e.printStackTrace();}"); out(" "+tm.make_unpack_var(ptype,"_retval","_unpackedret")); out(" "+ptype.returnvar("_unpackedret")); out(" "+Text.end+" }"); // FooPP.meth out(" add: to: "+cn+"PP { "+host.toIntSigStr("_PP",args)+ " throws java.rmi.RemoteException "+Text.begin); out(pp_body); out(" "+tm.pp_makeretvar(host,"_retval")); out(" "+tm.pp_makecallreal(host,"_retval","(("+cn+") _real)."+host.get_name()+"_hidden("+pp_realargs+")")+";"); out(" "+tm.make_pack_var(ptype,"_retval","_packedret")); // not a typo ^^^^^ // we need to tell pack var what the type of the unpacked var is.. // in this case it is host.get_returntype(), which is stored in ptype out(" "+pptype.returnvar("_packedret")); out(" "+Text.end+" }" ); @) } } Method { public MethodName get_name() to MethodName { before MethodName (@ return_val = host; @) } } Args { TransferMode findTransferMode(String pm, JavaType jt) to * { (@ boolean found = false; @) start (@ if (jt.objtype()) return_val = TransferMode.parse("gref"); else if (jt.voidtype()) return_val = TransferMode.parse("notpassed"); else return_val = TransferMode.parse("copy"); @) before ObjectName (@ found = pm.equals(host.toString()); @) before TransferMode (@ if (found) return_val = host; @) finish (@ if (! return_val.semanticcheck(jt)) System.err.println("INSANE!: "+ jt.toString()+" passed by "+return_val.toString()); @) } } TransferMode { boolean semanticcheck(JavaType t) to {GlobalRef, Copy, NotPassed} { before GlobalRef (@ return_val = t.objtype(); @) before Copy (@ return_val = !t.voidtype(); @) before NotPassed (@ return_val = true; @) } }