package platformSpecific.javaTranslation; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import tools.Assertions; import tools.StringBuilders; import ast.Ast; import ast.Ast.Type; import ast.Ast.Path; import ast.Ast.Position; import ast.Ast.NormType; import ast.ExpCore.ClassB; import ast.ExpCore.ClassB.Member; import ast.ExpCore.ClassB.MethodWithType; import programReduction.Program; public class TranslateClass { public static void of(Program p, String s, ClassB ct, StringBuilder res) { //classes that should exists only as class obj any for metaprogramming, are also interfaces here //not any more as 14 03/2016? boolean isInterface=getClassOpen(s,ct,res); res.append("{\n"); if(!isInterface){ generateClassFacade(s, ct, res); } else{ generateInterfaceFacade(s, ct, res); } getMethods(p,ct,res,isInterface); res.append("}"); } private static void generateInterfaceFacade(String s, ClassB ct, StringBuilder res) { getPhNestedNotIntantiable(s,ct,res,true); getIType(s,ct,res); } private static void generateClassFacade(String s, ClassB ct, StringBuilder res) { List<MethodWithType> ctors = extractConstructors(ct); if(ctors.isEmpty()){ getReverterForNotInstantiableClass(s,res); getPhNestedNotIntantiable(s,ct,res,false); getTypeForNotInstantiableClass(s,res); return; } MethodWithType ctor=ctors.get(0); getFields(ctor,res); getConstructor(s,ctor,res); getReverter(s,ctor,res); getGettesSettersAndExposers(ct,res); getPhNested(s,ctor,res); getType(s,ctors,res); } private static void getTypeForNotInstantiableClass(String s, StringBuilder res) { assert !s.contains("%"): "break"; res.append("public static final "+s+" type=new "+s+"();"); } private static void getITReverter(String s,StringBuilder res) { res.append("public ast.ExpCore revert(){\n"); pathReverter(s, res); } private static void getReverterForNotInstantiableClass(String s,StringBuilder res) { res.append("public ast.ExpCore revert(){\n"); res.append("if(this!=type){throw new Error(\"Impossible to revert an instance of a not instantiable class, how you get this instance?\");}\n"); pathReverter(s, res); } private static void pathReverter(String s, StringBuilder res) { Path path=Path.parse(Resources.name42Of(s)); int hash=path.outerNumber(); String cs=path.toString(); assert cs.contains("."): cs; cs=cs.substring(cs.indexOf(".")); res.append( "return platformSpecific.javaTranslation.Resources.fromHash("+hash+",\""+cs+"\").revert();\n"); res.append("}\n"); } private static void getReverter(String s, MethodWithType ctor,StringBuilder res) { res.append("public ast.ExpCore revert(){\n"); //pathReverter(s, res);//no, much worst here Path path=Path.parse(Resources.name42Of(s)); int hash=path.outerNumber(); String cs=path.toString(); cs=cs.substring(cs.indexOf(".")); res.append( "ast.ExpCore receiver= (ast.ExpCore)platformSpecific.javaTranslation.Resources.fromHash("+hash+",\""+cs+"\").revert();\n"); res.append("if(this==type){return receiver;}\n"); //res.append("java.util.ArrayList<String> xs=new java.util.ArrayList<>(java.util.Arrays.asList("); List<String> ns = ctor.getMs().getNames(); //StringBuilders.formatSequence(res,ns.iterator(), // ", ",n->res.append("\""+n+"\"")); //res.append("));\n"); res.append("java.util.ArrayList<ast.ExpCore> es=new java.util.ArrayList<>(java.util.Arrays.asList("); StringBuilders.formatSequence(res,ns.iterator(), ", ",n->res.append( "platformSpecific.javaTranslation.Resources.Revertable.doRevert(this.F"+Resources.nameOf(n)+")" )); res.append("));\n"); res.append("return new ast.ExpCore.MCall(receiver,"+ctor.getMs().toSrcEquivalent()+",ast.Ast.Doc.empty(),es,null);\n"); res.append("}\n"); } private static boolean getClassOpen(String s, ClassB ct, StringBuilder res) { boolean isInterface=ct.isInterface(); res.append("public "); if(isInterface){ res.append("interface "); if(!ct.getDoc1().isEmpty()){res.append("/*"+ct.getDoc1().toString()+"*/");} } else{res.append("class ");} res.append(s); System.out.println("creating class "+s); if(isInterface){res.append(" extends ");} else{res.append(" implements ");} res.append("platformSpecific.javaTranslation.Resources.Revertable"); Set<String> supt=new HashSet<>(); for(Path pi:ct.getSuperPaths()/*getStage().getInheritedPaths()*/){ if (pi.equals(Path.Any())){continue;} assert !pi.isPrimitive(); String resName=Resources.nameOf(pi); if(resName.equals("Object")){continue;} boolean notThere=supt.add(resName); if(notThere){ res.append(", "); res.append(resName); } } return isInterface; } private static List<MethodWithType> extractConstructors(ClassB ct) { List<MethodWithType> result=new ArrayList<>(); for(Member m:ct.getMs()){ assert m instanceof MethodWithType; MethodWithType mt=(MethodWithType)m; if(mt.get_inner().isPresent()){continue;} if(mt.getMt().getMdf()!=Ast.Mdf.Class){continue;} result.add(mt); } return result; } private static void getFields(MethodWithType ctor, StringBuilder res) { List<String> ns = ctor.getMs().getNames(); List<Type> ts = ctor.getMt().getTs(); StringBuilders.formatSequence(res,ns.iterator(),ts.iterator(), ";\n", (n,t)->{ assert t instanceof NormType; res.append("public "); res.append(Resources.nameOf(t)); res.append(" F"+Resources.nameOf(n)); }); res.append(";\n"); } private static void getConstructor(String s, MethodWithType ctor, StringBuilder res) { res.append("public "); res.append(s); res.append("( "); List<String> ns = ctor.getMs().getNames(); List<Type> ts = ctor.getMt().getTs(); StringBuilders.formatSequence(res,ns.iterator(),ts.iterator(), ", ",(n,t)->{ n=Resources.nameOf(n); res.append(Resources.nameOf(t)); res.append(" P"+n); }); res.append("){\n"); StringBuilders.formatSequence(res,ns.iterator(),ts.iterator(), "\n",(n,t)->{ n=Resources.nameOf(n); res.append("this."); res.append("F"+n); res.append("="); res.append("P"+n); res.append(";\n"); //if(d instanceof PhI<?>){((PhI<D>)d).addAction((val)->this.d=val);} res.append("if("); res.append("P"+n); res.append(" instanceof platformSpecific.javaTranslation.Resources.PhI<?>){((platformSpecific.javaTranslation.Resources.PhI<"+Resources.nameOf(t)+">)"); res.append("P"+n); res.append(").addAction((val)->this."); res.append("F"+n); res.append("=val);}\n"); }); res.append("}\n"); } private static void getGettesSettersAndExposers(ClassB ct, StringBuilder res) { for(Member m:ct.getMs()){ assert m instanceof MethodWithType; MethodWithType mt=(MethodWithType)m; if(mt.get_inner().isPresent()){continue;} if(mt.getMt().getMdf()==Ast.Mdf.Class){continue;}//constructor if(mt.getMt().getTs().isEmpty()){ getGetterOrExposer(mt,res); } else {getSetter(mt,res);} } } private static void getSetter(MethodWithType mt, StringBuilder res) { getMethodHeader(mt, res); res.append("{this."); String name=Resources.nameOf(mt.getMs().nameToS()); res.append("F"+name); res.append("=Pthat;return platformSpecific.javaTranslation.Resources.Void.instance;}"); } private static void getGetterOrExposer(MethodWithType mt, StringBuilder res) { getMethodHeader(mt, res); res.append("{return this."); String name=mt.getMs().nameToS(); if(name.startsWith("#")){name=name.substring(1);} name=Resources.nameOf(name); res.append("F"+name); res.append(";}"); } public static void getMethodHeader(MethodWithType mt, StringBuilder res) { res.append("\n@SuppressWarnings(\"unchecked\")"); res.append("\npublic "); res.append(Resources.nameOf(mt.getMt().getReturnType())); res.append(" "); res.append(Resources.nameOf(mt.getMs())); res.append("("); StringBuilders.formatSequence(res, mt.getMs().getNames().iterator(), mt.getMt().getTs().iterator(), ", ", (n,t)->{ n=Resources.nameOf(n); res.append(Resources.nameOf(t)); res.append(" P"+n); }); res.append(")\n"); } private static void getPhNested(String s, MethodWithType ctor, StringBuilder res) { res.append("public static final class Ph extends "); res.append(s+" implements platformSpecific.javaTranslation.Resources.PhI<"+s+">{\n"); res.append(" private final java.util.ArrayList<java.util.function.Consumer<"+s+">> actions=new java.util.ArrayList<>();\n"); res.append(" \n@SuppressWarnings(\"unchecked\")\n public void commit("+s+" val){ for(java.util.function.Consumer<"+s+"> r:actions){r.accept(val);} }"); res.append(" \n@SuppressWarnings(\"unchecked\")\n public void addAction(java.util.function.Consumer<"+s+"> r){actions.add(r);}"); res.append(" \n@SuppressWarnings(\"unchecked\")\n public Ph() {super("); StringBuilders.formatSequence(res, ctor.getMs().getNames().iterator(), ", ",n->res.append("null")); res.append(");}\n }\n"); } private static void getPhNestedNotIntantiable(String s,ClassB cb, StringBuilder res,boolean isInterface) { if(isInterface){ res.append("public static final class Ph implements "); res.append(s+", platformSpecific.javaTranslation.Resources.PhI<"+s+">{\n"); } else{ res.append("public static final class Ph extends "); res.append(s+" implements platformSpecific.javaTranslation.Resources.PhI<"+s+">{\n"); } res.append(" private final java.util.ArrayList<java.util.function.Consumer<"+s+">> actions=new java.util.ArrayList<>();\n"); res.append(" public void commit("+s+" val){ for(java.util.function.Consumer<"+s+"> r:actions){r.accept(val);} }"); res.append(" public void addAction(java.util.function.Consumer<"+s+"> r){actions.add(r);}"); res.append(" public ast.ExpCore revert()"); res.append("{throw new Error(\"PhInvocation\");}\n"); for(Member m:cb.getMs()){ MethodWithType mt=(MethodWithType)m; getMethodHeader(mt, res); res.append("{throw new Error(\"PhInvocation\");}\n"); } res.append(" public Ph(){ }\n }\n"); } private static void getType(String s, List<MethodWithType>ctors, StringBuilder res) { res.append("public static final "+s+" type=new "+s+"("); StringBuilders.formatSequence(res,ctors.get(0).getMs().getNames().iterator(), ", ",n->res.append("null")); res.append(");\n"); for(MethodWithType cti:ctors){ getMethodHeader(cti, res); res.append("{return new "+s+"("); StringBuilders.formatSequence(res,cti.getMs().getNames().iterator(), ", ",n->res.append("P"+Resources.nameOf(n))); res.append(");}\n"); } } private static void getIType(String s, ClassB cb, StringBuilder res) { res.append("public static final "+s+" type=new "+s+"(){\n"); getITReverter(s,res); for(Member m:cb.getMs()){ MethodWithType mt=(MethodWithType)m; getMethodHeader(mt, res); res.append("{throw new Error(\""+"Calling an interface method"+":"+mt.getMs()+"\");}\n"); } res.append("};\n" ); } private static void getMethods(Program p,ClassB ct, StringBuilder res,boolean isInterface) { for(Member m:ct.getMs()){ assert m instanceof MethodWithType; MethodWithType mt=(MethodWithType)m; if( !isInterface && !mt.get_inner().isPresent()){continue;} //if(mt.getMt().getMdf()!=Ast.Mdf.Type){continue;} getMethod(p,mt,res); } } private static void getMethod(Program p,MethodWithType mt, StringBuilder res) { getMethodHeader(mt, res); if(mt.get_inner().isPresent()){ TranslateExpression.of(mt.getInner(),res); } else{res.append(";\n");} } }