package auxiliaryGrammar; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; import facade.Configuration; import platformSpecific.javaTranslation.Resources; import tools.Assertions; import ast.Ast; import ast.ExpCore; import ast.Ast.Doc; import ast.Ast.Mdf; import ast.Ast.NormType; import ast.Ast.Path; import ast.Ast.Position; import ast.Ast.SignalKind; import ast.Ast.Stage; import ast.Ast.Type; import ast.ExpCore.ClassB; import ast.ExpCore.EPath; import ast.ExpCore.Using; import ast.ExpCore._void; public class EncodingHelper{ //encoding //'@int32" // '0" //'@stringU" // 'fuffa\u0b12bar" //only works for unicode16bit public static String/*with unicode inside*/ parseStringUnicode(String s/*with \uFFFF inside*/){ StringBuilder result=new StringBuilder(); for(int i=0;i<s.length();i++){ char c=s.charAt(i); if(c!='\\'){result.append(c);continue;} if(i+5>=s.length()){throw Assertions.codeNotReachable("Invalid string encoding:\n"+s);} if(s.charAt(i+1)!='u'){throw Assertions.codeNotReachable("Invalid string encoding:\n"+s);} char uc = (char)Integer.parseInt( s.substring(i+2,i+6), 16 ); result.append(uc);i=i+5; } return result.toString(); } static boolean isValid42Char(char c){ String symbols=" ~!@#$%^&*()_-=+{}[]:;\"\'\\<>,.?/"; if(symbols.indexOf(c)!=-1){return true;} if(c>='a'&& c<='z'){return true;} if(c>='A'&& c<='Z'){return true;} if(Character.isDigit(c)){return true;} return false; } public static String/*with \uFFFF inside*/ produceStringUnicode(String s/*with unicode inside*/) { StringBuilder result=new StringBuilder(); for(int i=0;i<s.length();i++){ char c=s.charAt(i); if(c=='\\'){addAsUnicode(result,c);continue;} if(c=='@'){addAsUnicode(result,c);continue;}//otherwise, the special meaning of @ in comments mess up with string encoding if(isValid42Char(c)){result.append(c);continue;} addAsUnicode(result,c); } return result.toString(); } static void addAsUnicode(StringBuilder result, char c) { result.append("\\u"); result.append(String.format("%04x", (int) c)); } public static String composedName(Using u) { String result=u.getS().nameToS()+" "; for(String s:u.getS().getNames()){result+=s+" ";} return result; } public static ExpCore wrapError(String err) { return new ExpCore.Signal(SignalKind.Error,wrapStringU(err),Path.Library().toImmNT(),Path.Library().toImmNT()); } public static ClassB wrapInt32(int i) { return wrapInt32(""+i); } public static ClassB wrapInt32(String i) { return ClassB.docClass(Doc.factory(true,"@int32\n"+i+"\n")); } public static ClassB wrapBool(boolean b) { String s="@boolTrue\n"; if(!b)s="@boolFalse\n"; return ClassB.docClass(Doc.factory(true,s)); } public static ClassB wrapStringU(String s) { return ClassB.docClass(Doc.factory(true,"@stringU\n"+produceStringUnicode(s)+"\n")); } public static Doc ensureExtractDoc(Object e) { if(e instanceof Doc){return (Doc)e;} ClassB cb=ensureExtractClassB(e); return cb.getDoc1(); } public static ClassB ensureExtractClassB(Object e) { ClassB res=_extractClassB(e); if (res==null ){ throw new Resources.Error("InvalidClassB for ensureExtractClassB"); } return res; } public static ClassB _extractClassB(Object e) { if(e instanceof ClassB){return (ClassB)e;} if(e instanceof Integer){return wrapInt32((Integer)e);} if(e instanceof String){return wrapStringU((String)e);} return null; } public static <T> T ensureExtract(Class<T> clazz,Object e){ assert clazz!=null; if (e==null ){throw new Resources.Error("Invalid null "+clazz);} try{ return clazz.cast(e); } catch(ClassCastException cce){throw new Resources.Error("Invalid:"+clazz+" expected, but was: "+e.getClass());} } public static Integer ensureExtractInt32(Object e) { Integer res=_extractInt32(e); if (res==null ){throw new Resources.Error("InvalidInt32");} return res; } public static Integer _extractInt32(Object e) { if(e instanceof Integer){return (Integer)e;} if(!(e instanceof ClassB)){return null;} ClassB cb=(ClassB)e; String code=extractCode(cb,"@int32\n"); if(code==null){return null;} try{return Integer.parseInt(code);} catch(NumberFormatException nfe){return null;} } public static Boolean ensureExtractBool(Object e) { Boolean res=_extractBool(e); if (res==null ){throw new Resources.Error("InvalidBool");} return res; } public static Boolean _extractBool(Object e) { if(e instanceof Boolean){return (Boolean)e;} if(!(e instanceof ClassB)){return null;} ClassB cb=(ClassB)e; Object ann = cb.getDoc1().getAnnotations().get(0); if(ann.equals("boolTrue")){return true;} if(ann.equals("boolFalse")){return false;} return null; } public static Path ensureExtractPathFromJava(Object e) { Path res=_extractPathFromJava(e); if (res==null ){throw new Resources.Error("InvalidPath");} return res; } public static Ast.Path _extractPathFromJava(Object e) { if(e instanceof Ast.Path){return (Ast.Path)e;} if(e instanceof Resources.Any){return Path.Any();} if(e instanceof Resources.Library){return Path.Library();} if(e instanceof Resources.Void){return Path.Void();} assert e instanceof Resources.Revertable; return ((ExpCore.EPath) ((Resources.Revertable)e).revert()).getInner(); } public static String ensureExtractStringU(Object e) { String res=_extractStringU(e); if (res==null ){ System.out.println("Doh, invalid string"+e); throw new Resources.Error("InvalidStringU"); } return res; } public static String _extractStringU(Object e) { if(e instanceof String){return (String)e;} if(!(e instanceof ClassB)){return null;} ClassB cb=(ClassB)e; String code=extractCode(cb,"@stringU\n"); if(code==null){return null;} return EncodingHelper.parseStringUnicode(code); } static String extractCode(ClassB cb, String prefix) { if(cb.isInterface()){return null;} if(!cb.getMs().isEmpty()){return null;} String result=cb.getDoc1().toString(); if(!result.startsWith(prefix)){return null;} if(result.length()==prefix.length()){return "";} result=result.substring(prefix.length(),result.length()-1); return result; } public static Ast.MethodType mtType(Path result){ List<Type> ts=new ArrayList<>(); ts.add(NormType.classAny); return new Ast.MethodType(false,Mdf.Immutable,ts,result.toImmNT(),Collections.emptyList()); } public static Ast.MethodType mt(Path result,Path ...paths){ List<Type> ts=new ArrayList<>(); for(Path pi:paths){ ts.add(pi.toImmNT()); } return new Ast.MethodType(false,Mdf.Immutable,ts,result.toImmNT(),Collections.emptyList()); } public static ExpCore wrapResource(Object o) { if(o instanceof ClassB){return (ClassB)o;} if(o instanceof ExpCore){return (ExpCore)o;} if(o instanceof Integer){return wrapInt32((Integer)o);} if(o instanceof String){return wrapStringU((String)o);} if(o instanceof Resources.Void){return new ExpCore._void();} if(o instanceof Resources.Error){ ExpCore inside=wrapResource(((Resources.Error)o).unbox); return new ExpCore.Signal(SignalKind.Error,inside,null,null); } if(o instanceof Resources.Exception){ ExpCore inside=wrapResource(((Resources.Exception)o).unbox); return new ExpCore.Signal(SignalKind.Exception,inside,null,null); } if(o instanceof Resources.Return){ ExpCore inside=wrapResource(((Resources.Return)o).unbox); return new ExpCore.Signal(SignalKind.Return,inside,null,null); } if( o instanceof Resources.Library){ return EPath.wrap(Ast.Path.Library()); } if( o instanceof Resources.Void){ return EPath.wrap(Ast.Path.Void()); } if( o instanceof Resources.Any){ return EPath.wrap(Ast.Path.Any()); } if(o instanceof Resources.Revertable){return ((Resources.Revertable)o).revert();} return wrapResource(o.toString()); } //javaFullName can contains dots but not % //"." converted in "%" and unicode weirdos converted in "%%u..." //since no two dots in a row are allowed public static String javaClassToX(int parNum,String that){ that=produceStringUnicode(that);//now all \\u inside, no other \ inside that=that.replace("\\u", "%%"); return "_"+parNum+"_"+that.replace(".","%"); } public static String xToJavaClass(String that){ assert that.charAt(0)=='_'; that=that.substring(1); assert that.indexOf("_")!=-1:that; that=that.substring(that.indexOf("_")+1); if(that.equals("Library")){return ExpCore.ClassB.class.getName();} that=that.replace("%%%", ".%%"); that=that.replace("%%", "\\u"); that=that.replace("%", "."); that=parseStringUnicode(that); return that; } }