package edu.neu.ccs.demeterf.inline; import edu.neu.ccs.demeterf.Control; import edu.neu.ccs.demeterf.TU; import edu.neu.ccs.demeterf.Traversal; import edu.neu.ccs.demeterf.demfgen.ClassHier.InhrtPair; import edu.neu.ccs.demeterf.demfgen.ClassHier.InhrtStr; import edu.neu.ccs.demeterf.demfgen.classes.*; import edu.neu.ccs.demeterf.demfgen.DemFGenMain; import edu.neu.ccs.demeterf.lib.List; import edu.neu.ccs.demeterf.lib.Option; import edu.neu.ccs.demeterf.lib.ident; public class SubTyping{ public static String ObjectName = "Object", WildName = "$$"; static TypeUse obj = new TypeUse(new ident(ObjectName),new EmptyUseParams()), wild = new TypeUse(new ident(WildName),new EmptyUseParams()); static boolean JAVA_HACK = false; static boolean STRICT = false; static void pl(String s){ System.out.println(s); } static void p(String s){ System.out.print(s); } static String[][] prims = new String[][]{ {"Integer","int"}, {"Long","long"}, {"Short","short"}, {"Double","double"}, {"Float","float"}, {"Boolean","boolean"} }; static List<FieldOrSyntax> nofields = List.create(); static List<TypeUse> nouses = List.create(); static List<String> nopars = List.create(); static List<InhrtPair> primSubs = List.<String[]>create(prims).fold(new List.Fold<String[], List<InhrtPair>>(){ public List<InhrtPair> fold(String[] ex, List<InhrtPair> r){ return r.push(new InhrtPair(new InhrtStr(ex[0],nopars,nofields),ex[1],nouses)) .push(new InhrtPair(new InhrtStr(ex[1],nopars,nofields),ex[0],nouses)); } },List.<InhrtPair>create()); List<InhrtPair> tenv; public SubTyping(List<CDFile> CD){ tenv = DemFGenMain.subtypes(addFieldClasses(CD)); } /** Add the subtype relationships for the (implied) to be generated Field Classes for * checking and generating calles for "update" methods */ public static List<CDFile> addFieldClasses(List<CDFile> CDs){ List<String> fields = new Traversal(new TU<List<String>>(){ List<String> mt = List.create(); public List<String> combine(){ return mt; } public List<String> fold(List<String> a, List<String> b){ return a.append(b); } public List<String> combine(ClassDef c, DoGen d, final ident id, TypeDefParams p, PESubtypeList sts, List<String> fs){ return fs.map(new List.Map<String, String>(){ public String map(String s){ return id+s; } }); } List<String> combine(Field f){ return mt.push("$"+f.getName()); } }, Control.bypass(ClassDef.class).removeBypassing(ClassDef.class,"fields")).traverse(CDs); try{ ClassDef fcs = ClassDef.parse(" Fields$any = "+fields.toString(" | ", "")+"."); return CDs.pop().push(CDs.top().addType(fcs)); }catch(ParseException pe){ throw new RuntimeException("Unable to Create Field Class Defs: "+pe.getMessage()); } } public String toString(){ return "subtypeing{\n"+tenv.toString("\n", " ")+"\n}"; } /** Find the super class of the given Type */ public TypeUse supertype(final TypeUse t){ List<InhrtPair> sups = tenv.filter(new List.Pred<InhrtPair>(){ public boolean huh(InhrtPair p){ return p.child().equals(""+t.getName()); } }); if(sups.isEmpty())return obj; return TypeUse.makeType(sups.top().parent()+t.getTparams().print()); } public TypeUse make__Type(String s){ try{ return TypeUse.parse(s); }catch(Exception e){ throw new RTParseException(e.getMessage()); } } /** Is the first a subtype (<=) of the second? */ public boolean subtype(TypeUse t, TypeUse u){ if(subtype(""+t.getName(),""+u.getName()) && (JAVA_HACK || t.getTparams().length() == u.getTparams().length())){ if(JAVA_HACK)return true; List<TypeUse> ups = u.getTparams().toTUList(); for(TypeUse tu:t.getTparams().toTUList()){ if(!subtype(tu,ups.top()))return false; ups = ups.pop(); } return true; } return false; } public boolean subtype(List<TypeUse> ts, List<TypeUse> us){ if(ts.isEmpty())return us.isEmpty(); if(us.isEmpty())return false; return (subtype(ts.top(),us.top()) && subtype(ts.pop(),us.pop())); } /** Are the given actual argument types applicable to the formal types? */ public boolean applicable(List<TypeUse> form, List<TypeUse> act){ return applicableStar(form,act.map(new List.Map<TypeUse, Option<TypeUse>>(){ public Option<TypeUse> map(TypeUse u){ return Option.some(u); } })); } /** Are the given actual argument types applicable to the formal types? */ public boolean applicableStar(List<TypeUse> form, List<Option<TypeUse>> act){ if(form.isEmpty())return !STRICT || act.isEmpty(); if(act.isEmpty())return false; return ((!act.top().isSome() || subtype(act.top().inner(),form.top())) && applicableStar(form.pop(),act.pop())); } /** Are the given actual argument types applicable to the formal types? */ public boolean possible(List<TypeUse> form, List<TypeUse> act){ return possibleStar(form,act.map(new List.Map<TypeUse, Option<TypeUse>>(){ public Option<TypeUse> map(TypeUse u){ return Option.some(u); } })); } /** Are the given actual argument types applicable to the formal types? */ public boolean possibleStar(List<TypeUse> form, List<Option<TypeUse>> act){ if(form.isEmpty())return !STRICT || act.isEmpty(); if(act.isEmpty())return false; return ((!act.top().isSome() || subtype(act.top().inner(),form.top()) || subtype(form.top(),act.top().inner())) && possibleStar(form.pop(),act.pop())); } /** Check if a given type name is a subtype of another */ private boolean subtype(String t, String u){ if(u.equals(ObjectName) || u.equals(WildName) || t.equals(u))return true; ChildMatch mtch = new ChildMatch(t); if(primSubs.contains(mtch)) return u.equals(primSubs.find(mtch).parent()); // Subtype edges *to* the type "t" List<InhrtPair> app = tenv.filter(mtch); // See if "u" is one of the *from* types return (app.contains(new ParMatch(u)) || // Or check recursively... Note: this is only the primary type, not // any type arguments app.contains(new RecMatch(u,this))); } static class ChildMatch extends List.Pred<InhrtPair>{ String str; ChildMatch(String s){ str = s; } public boolean huh(InhrtPair p){ return p.child().equals(str); } } static class ParMatch extends ChildMatch{ ParMatch(String s){ super(s); } public boolean huh(InhrtPair p){ return p.parent().equals(str); } } static class RecMatch extends ChildMatch{ SubTyping sub; RecMatch(String s, SubTyping st){ super(s); sub = st; } public boolean huh(InhrtPair p){ return sub.subtype(p.parent(),str); } } }