package edu.neu.ccs.demeterf.demfgen; import edu.neu.ccs.demeterf.demfgen.classes.*; import edu.neu.ccs.demeterf.util.Util; import edu.neu.ccs.demeterf.demfgen.ClassHier.*; import edu.neu.ccs.demeterf.demfgen.pcdgp.PCDGPFunc; import edu.neu.ccs.demeterf.inline.SubTyping; import edu.neu.ccs.demeterf.lib.List; import edu.neu.ccs.demeterf.lib.ident; import edu.neu.ccs.demeterf.demfgen.ClassGen.PackDesc; import edu.neu.ccs.demeterf.*; import edu.neu.ccs.demeterf.demfgen.traversals.Travs; /** Class that encapsulates the class generation portion of DemFGen */ public class ClassGen extends PackGen{ ClassGen(List il, List b, String dg, List opts, List pcs, PackageDef pkg) { super(il,b,dg,opts,pcs,pkg); } static boolean quiet = Diff.optionSet(Diff.quiet); static void p(String s){{ if(!quiet)System.err.print(s); }} /** Generate the class (source) files for the given CD */ public static List genClasses(List CD, List BEH, String dir, String dgp, List opts, List inhrt, List pcdgps, PackageDef basepkg){ quiet = Diff.optionSet(Diff.quiet); ClassGen cgen = new ClassGen(inhrt, BEH, dgp, opts, pcdgps, basepkg); p(" ["); Travs.TheFactory.makeClassGenTrav(cgen).traverse(CD, PackDesc.start(dir)); p("]\n"); return inhrt; } public static String unlocal(ident id){ return unlocal(id.toString()); } public static String unlocal(TypeUse tu){ return unlocal(""+tu); } public static String unlocal(TypeDefParams dp){ return unlocal(dp.toString()); } public static String unlocal(String s){ return (s.replaceAll("[ ]+", " ").replace('(','<').replace(')','>') .replace(SubTyping.WildName,"?").replace('$','.')); } static List Primitives = Diff.d.builtIns.map(new List.Map(){ public ArityPair map(String s){ return new ArityPair(s,0); } }); public static class PackDesc{ private String dir, header; private PackageDef pkg; public static PackDesc start(String d){ return new PackDesc(d,new NoPackage(),"",true); } private PackDesc(String d, PackageDef p, String head, boolean gen){ dir = DemFGenMain.pkgdir(d, p, gen); pkg = p; header = Preamble.header+head+"\n"; } public PackDesc update(PackageDef p, ImportList i, boolean gen){ return new PackDesc(dir, p, p+""+i, gen); } public boolean hasPkg(){ return pkg.hasPkg(); } public String getDir(){ return dir; } public String nameDot(){ return hasPkg()?pkg.name()+".":""; } public String toString(){ return header+"\n"; } } static class EqStringer extends List.Stringer{ public String toString(String f, List r){ return "("+(Diff.isJava()?"((Object)"+f+")":f)+"."+Diff.d.equalsMethod+ "(oo."+f+"))"+(r.isEmpty()?"":"&&"); } } static class HashStringer extends List.Stringer{ static List hashes = List.create(1,3,5,7,13,17,19,23); public String toString(String f, List r){ int which = r.length()%hashes.length(); return ("("+hashes.lookup(which)+"*("+ (Diff.isJava()?"((Object)"+f+")":f)+"."+Diff.d.hashMethod+"()))"+ (r.isEmpty()?"":"+")); } } public static class ArityPair{ String name; int arity; public ArityPair(String name, int arity){ this.name = name; this.arity = arity; } public boolean equals(Object o){ if(!(o instanceof ArityPair))return false; ArityPair oo = (ArityPair)o; return name.equals(oo.name); } public String toString(){ return name+"("+arity+")"; } } public static class ToList extends FC{ public ArityPair combine(NameDef d){ return new ArityPair(""+d.getId(), 0); } public List combine(EmptyList e){ return List.create(); } public List combine(ConsList c, ArityPair a, List r){ return r.push(a); } public List combine(Object o, List r){ return r; } } public static class ToTDList extends ToList{ public ArityPair combine(TypeDef td){ return new ArityPair(""+td.name(), td.typeParams().length()); } } public static class InhrtFor extends List.Pred{ String cls; InhrtFor(String c){ cls = c; } public boolean huh(InhrtPair p){ return cls.equals(p.chld); } } public static class Extnds extends List.Pred{ public boolean huh(InhrtPair p){ return p.extend(); } } public static class Intfcs extends Extnds{ public boolean huh(InhrtPair p){ return !super.huh(p); } } } class PackGen extends Gen{ PackGen(List il, List b, String dg, List opts, List pcs, PackageDef pkg) { super(il,b, dg, opts, pcs, pkg); } public PackDesc update(CDFile m, Fields.any f, PackDesc p){ return p.update(m.getPkg(), m.getImports(), m.getTypes().anyGen()); } public String combine(CDFile m){ return ""; } public String combine(List l, String f, String r){ return ""; } public String combine(List l){ return ""; } public String combine(Impl imp){ return ""; } } class Gen extends FC{ List inhrt; List beh; String dgpMeths; boolean parser; boolean mutable; String fieldPriv; List opts; List pcdgps; PackageDef basepkg; Gen(List il, List b, String dg, List ops, List pcs, PackageDef pkg){ inhrt = il; beh = b; dgpMeths = dg; opts = ops; pcdgps = pcs; parser = !Diff.optionSet(Diff.noparse); mutable = Diff.optionSet(Diff.mutable); fieldPriv = Diff.optionSet(Diff.pubfields)?Diff.d.pubPriv:Diff.d.protPriv; basepkg = pkg; } String writeFile(String cName, String cls, String header, PackDesc pd){ ClassGen.p(cName+", "); return Util.writeFile(cName, "."+Diff.d.fileSuffix, cls, pd.getDir(), header); } public String combine(TypeUse e, ident i, String s){ return i+s; } //ident combine(Ident i){ return new ident(""+i); } public EmptyList combine(EmptyList e){ return e; } //StrLTrip combine(ProdType p, StrLTrip lt){ return lt; } public StrLTrip combine(FieldList l, StrLTrip.StrTrip tr, StrLTrip tl){ return tl.add(tr.f, tr.a, tr.t); } public StrLTrip combine(FieldList l, Syntax s, StrLTrip tl){ return tl; } public StrLTrip.StrTrip combine(Field f, ident n, String t){ return new StrLTrip.StrTrip(t+" "+n, "this."+n+" = "+n+";",""+n); } public String extensions(String name, final List params){ List inhrtL = inhrt.filter(new ClassGen.InhrtFor(name)), extnd = inhrtL.filter(new ClassGen.Extnds()), intfc = inhrtL.filter(new ClassGen.Intfcs()); if(extnd.length() > 1)throw new TE("Too Many Extensions!! For: "+name+" ["+extnd+"]"); return Diff.d.extensions(name, extnd, intfc, params); } public StrLTrip superTriples(String name, List params){ return ClassHier.superFields(params,inhrt,name).foldr(new List.Fold(){ public StrLTrip fold(Field f, StrLTrip st) { return st.add(""+f.getType()+" "+f.getName(), "", ""+f.getName());} }, new StrLTrip()); } public StrLTrip combine(FieldEmpty e){ return new StrLTrip(); } String parseMethods(TypeDefParams p, String n, String tp, DoGen g){ String method = ".parse_"+n+ParseGen.ProductGen.typeMethod(tp)+"();\n"; String ovrd = Diff.d.isCS()?"new ":""; String parse = Diff.capName("parse("); String pkgpre = basepkg.nameDot(); String newp = " return new "+pkgpre+"TheParser("; return ((parser && g.doParse() && p.length() == 0)? " /** Parse an instance of "+n+" from the given String */\n"+ " public static "+ovrd+n+tp+" "+parse+"String inpt) "+ Diff.d.parseException(pkgpre)+"{\n"+newp+"new "+Diff.d.stringInput+"(inpt))"+method+" }\n"+ " /** Parse an instance of "+n+" from the given Stream */\n"+ " public static "+ovrd+n+tp+" "+parse+Diff.d.inputStream+" inpt) "+ Diff.d.parseException(pkgpre)+"{\n"+newp+"inpt)"+method+" }\n"+ " /** Parse an instance of "+n+" from the given Reader */\n"+ " public static "+ovrd+n+tp+" "+parse+Diff.d.inputReader+" inpt) "+ Diff.d.parseException(pkgpre)+"{\n"+newp+"inpt)"+method+" }\n":""); } String pcdgpMethods(final TypeDef td, final List superFs){ try{ final TypeDef ntd = ClassHier.addSuperFields(td, inhrt); return pcdgps.fold(new List.Fold(){ public String fold(PCDGPFunc f, String r){ return r+new StaticTrav(f.functionObj(superFs), f.control()).traverse(ntd); } },""); }catch(Exception e){ ClassGen.p("\n !! PCDGPError: "+e.getMessage()+"\n\n"); System.exit(1); return null; } } public String combine(ClassDef td, DoGen g, ident n, TypeDefParams dp, PESubtypeList stl, StrLTrip body, String imp, PackDesc pkg){ String tpb = Diff.d.bndStr.str(dp), cp = Diff.d.constrStr.str(dp), up = Diff.d.useStr.str(dp); if(!g.doGen())return ""; boolean abstr = !stl.isEmpty() && (!Diff.optionSet(Diff.concretes) || body.isEmpty()); StrLTrip supFs = superTriples(""+n,dp.toList()); StrLTrip allFs = body.append(supFs); String supConst = "("+supFs.fNames.toString(", ", "")+")"; String cls = ("\n\n"+ "/** Representation of "+n+up+" */\n"+ "public "+(abstr?"abstract ":"")+"class "+n+tpb+extensions(""+n,dp.toList())+cp+"{\n"+ body.fieldDefs(fieldPriv+(mutable?"":" "+Diff.d.fieldImmut))+ "\n"+ " /** Construct a(n) "+n+up+" Instance */\n"+ " public "+n+"("+allFs.arguments()+")"+ (!supFs.isEmpty()&&Diff.isCS()?" : base"+supConst:"")+ "{\n"+(!supFs.isEmpty()&&Diff.isJava()?" super"+supConst+";\n":"")+ body.assignments()+(body.assigns.isEmpty()?"":"\n")+ " }\n"+ (stl.isEmpty() && !Diff.optionSet(Diff.noequals)? " /** Is the given object Equal to this "+n+"? */\n"+ " public"+Diff.d.override+" "+Diff.d.equalsRet+" "+Diff.d.equalsMethod+"(Object o){\n"+ " if(!(o"+Diff.d.instanceCheck(""+n,up)+"))return false;\n"+ " if(o == this)return true;\n"+ " "+n+up+" oo = ("+n+up+")o;\n"+ " return "+(allFs.fNames.isEmpty()?"true": allFs.fNames.toString(new ClassGen.EqStringer()))+";\n"+ " }\n":"")+ parseMethods(dp,""+n,up,g)+ body.fieldClasses(""+n)+"\n"+ DemFGenMain.behBody(this.beh, ""+n)+"\n"+dgpMeths+ pcdgpMethods(td,supFs.fNames)+"\n}\n"+ (pkg.hasPkg()?Diff.d.classEnd:"")+"\n"); return writeFile(""+n, cls,""+pkg+Diff.d.basicImport,pkg); } public String combine(TypeDefList l, String f, String r){ return f+"\n"+r; } public String combine(TypeDefEmpty l){ return ""; } public String combine(TypeUseCons c, String t, String r){ return ", "+t+r; } public String combine(NETypeUseList tu, String t, String r){ return "<"+t+r; } public String combine(TypeUseEmpty e){ return ">"; } public String combine(UseParams dp, String s){ return s; } public String combine(EmptyUseParams dp){ return ""; } public String combine(IntfcDef id, DoGen g, ident n, TypeDefParams dp, PESubtypeList stl, PackDesc pkg){ String tp = Diff.d.bndStr.str(dp); if(g.doGen()) return writeFile(""+n, "/** Interface representation of "+n+tp+" */\n"+ "public interface "+n+tp+ "{\n"+DemFGenMain.behBody(this.beh, ""+n)+ pcdgpMethods(id, List.create())+"\n}\n"+ (pkg.hasPkg()?Diff.d.classEnd:"")+"\n", ""+pkg+Diff.d.basicImport,pkg); return ""+n; } }