Adding sypet to repo
[Benchmarks_CSolver.git] / sypet / src / edu / utexas / sypet / synthesis / SyPetService.java
diff --git a/sypet/src/edu/utexas/sypet/synthesis/SyPetService.java b/sypet/src/edu/utexas/sypet/synthesis/SyPetService.java
new file mode 100644 (file)
index 0000000..5a6dcab
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2017 The SyPet Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.utexas.sypet.synthesis;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.gson.Gson;
+
+import edu.utexas.hunter.model.CustomMethod;
+import edu.utexas.hunter.model.CustomType;
+import edu.utexas.sypet.SypetEnv;
+import edu.utexas.sypet.synthesis.model.JEdge;
+import edu.utexas.sypet.synthesis.model.JGraph;
+import edu.utexas.sypet.synthesis.model.JNode;
+import edu.utexas.sypet.synthesis.model.Pair;
+import edu.utexas.sypet.util.SootUtil;
+import edu.utexas.sypet.util.SynthUtil;
+import uniol.apt.adt.pn.PetriNet;
+import uniol.apt.adt.pn.Place;
+import uniol.apt.adt.pn.Transition;
+
+public class SyPetService {
+
+       private PetriNet pNet = new PetriNet();
+
+       private final String UNSAT = "UNSAT";
+
+       private final int minLocal = 2;
+       
+       private final int maxLocal = 7;
+
+       private final int maxTokens = 8;
+
+       private PathFinder pf;
+
+       private Sketcher sk;
+
+       private boolean hasPath = false;
+
+       private boolean hasSketch = false;
+
+       private boolean hasInit = false;
+
+       private List<Pair<String, String>> srcPairs;
+
+       private String tgtType;
+       
+       private static final String UPPER = "_upper";
+       
+       private static final String SDK = "_sdk";
+       
+       public static Map<String, Pair<String,String>> sdkTypes = new HashMap<>();
+
+       
+       // default type conversion graph.
+       public static final String JDKGRAPH = "edu/utexas/hunter/synthesis/JDK.json";
+
+       public SyPetService() {
+               /// init basic petrinet
+               // InputStream is = getClass().getClassLoader().getResourceAsStream(JDKGRAPH);
+               InputStream is = getClass().getClassLoader().getResourceAsStream("JDK.json");
+               Gson gson = new Gson();
+               BufferedReader br;
+               
+               br = new BufferedReader(new InputStreamReader(is));
+               JGraph graph = gson.fromJson(br, JGraph.class);
+               graph.buildDependency();
+
+               // handle uppercast.
+               int upperCnt = 0;
+               for (JNode node : graph.getNodes()) {
+                       Set<JNode> uppers = graph.upperCastSet(node);
+                       String srcName = node.getName();
+                       if (uppers.isEmpty())
+                               continue;
+
+                       if (!pNet.containsNode(srcName))
+                               pNet.createPlace(srcName);
+
+                       for (JNode tgt : uppers) {
+                               String tgtName = tgt.getName();
+                               String tranName = UPPER + upperCnt;
+                               pNet.createTransition(tranName);
+                               if (!pNet.containsNode(tgtName))
+                                       pNet.createPlace(tgtName);
+
+                               pNet.createFlow(srcName, tranName);
+                               pNet.createFlow(tranName, tgtName);
+                               sdkTypes.put(tranName, new Pair<>(srcName,tgtName));
+                               upperCnt++;
+                       }
+               }
+
+               // handler build-in functions.
+               for (JEdge e : graph.getEdges()) {
+                       String label = e.getLabel();
+                       String src = graph.getNode(e.getSource()).getName();
+                       String tgt = graph.getNode(e.getTarget()).getName();
+
+                       if ("?".equals(label))
+                               continue;
+
+                       String tranName = label + SDK + upperCnt;
+                       sdkTypes.put(tranName, new Pair<>(src,tgt));
+
+                       SootUtil.createPlace(pNet, src);
+                       SootUtil.createPlace(pNet, tgt);
+                       SootUtil.createTransition(pNet, tranName);
+
+                       pNet.createFlow(src, tranName);
+                       pNet.createFlow(tranName, tgt);
+                       upperCnt++;
+               }
+               
+               // build-in jdk types.
+               
+               //void
+               SootUtil.createPlace(pNet, "void");
+       }
+
+       private void initSyPet(List<Pair<String, String>> srcs, String tgt, int localMax) {
+               List<Place> inits = new ArrayList<>();
+               List<String> types = new ArrayList<>();
+               srcPairs = srcs;
+               tgtType = tgt;
+
+               for (Pair<String, String> pair : srcs) {
+                       if(!pNet.containsPlace(pair.val0))
+                               pNet.createPlace(pair.val0);
+                       
+                       Place srcPlace = pNet.getPlace(pair.val0);
+                       types.add(pair.val0);
+                       inits.add(srcPlace);
+               }
+
+               // adding void to initial marking.
+               inits.add(pNet.getPlace("void"));
+               // Multiple args: check if we need put clone as initial constraints.
+               List<String> clones = SootUtil.getClones(types);
+               Place tgtPlace = pNet.getPlace(tgt);
+               pf = new PathFinder(pNet, inits, tgtPlace, localMax, maxTokens, null, clones);
+       }
+
+       public String doQuery() {
+               if(srcPairs == null) return "UNSAT";
+               
+               if(trivial(srcPairs.get(0).val0, tgtType)) {
+                       return "UNSAT";
+               }
+
+               assert!srcPairs.isEmpty();
+               return doQuery(srcPairs, tgtType);
+       }
+       
+       public boolean trivial(String src, String tgt) {
+               return (SynthUtil.isNum(src) && SynthUtil.isNum(tgt));
+       }
+
+       public String doQuery(List<Pair<String, String>> srcs, String tgt) {
+               if (SypetEnv.debug) {
+                       System.out.println("doQuery---------------------" + srcs + "------>" + tgt);
+                       System.out.println("hasInit " + hasInit);
+                       System.out.println("hasPath " + hasPath);
+               }
+
+
+               int localMax = minLocal;
+               if (!hasInit) {
+                       if(!pNet.containsPlace(tgt)) return UNSAT;
+                       initSyPet(srcs, tgt, localMax);
+                       hasInit = true;
+               }
+               String snippet = UNSAT;
+
+               while (true) {
+                       List<String> solution = new ArrayList<>();
+
+                       if (!hasPath) {
+                               List<String> res = pf.get();
+                               
+                               if(SypetEnv.debug)
+                                       System.out.println("localmax: " + localMax + " res:" + res);
+                               
+                               if (res.isEmpty()) {
+                                       if(localMax < maxLocal) {
+                                               localMax++;
+                                               initSyPet(srcs, tgt, localMax);
+                                               continue;
+                                       }
+                                               
+                                       reset();
+                                       return UNSAT;
+                               }
+
+                               for (String meth : res) {
+                                       if (meth.startsWith("sypet_clone_"))
+                                               continue;
+
+                                       solution.add(meth);
+                               }
+                               hasPath = true;
+                       }
+
+                       if (!hasSketch) {
+                               //System.out.println("solutions:" + solution);
+                               //upper cast?
+                               if((solution.size() == 1) && solution.get(0).contains("_upper"))
+                                       return srcs.get(0).val1;
+                               
+                               sk = new Sketcher(solution, srcs, tgt);
+                               boolean flag = sk.initSketch();
+                               if(!flag) {
+                                       //get another path.
+                                       hasPath = false;
+                                       continue;
+                               }
+                               hasSketch = true;
+                       }
+                       snippet = sk.fillHoles();
+                       if (UNSAT.equals(snippet)) {
+                               reset();
+                               continue;
+                       }
+                       break;
+               }
+
+               return snippet;
+       }
+       
+       public PetriNet buildPetri(String srcType, List<CustomType> customTypeList, String tgtType)
+                       throws Throwable {
+               if (customTypeList.isEmpty())
+                       return null;
+
+               SootUtil.createPlace(pNet, "void");
+               SootUtil.createPlace(pNet, srcType);
+               SootUtil.createPlace(pNet, tgtType);
+               if (SypetEnv.debug) {
+                       System.out.println("buildPetrinet---------------------");
+                       System.out.println("Construct Petrinet from: " + srcType + "->" + tgtType);
+                       System.out.println("src: " + srcType);
+                       System.out.println("tgt: " + tgtType);
+               }
+               
+               List<CustomType> linkedListTypes = new ArrayList<>();
+               List<CustomType> binTypes = new ArrayList<>();
+
+               for (CustomType type : customTypeList) {
+                       if (SootUtil.isLinkedlist(type)) {
+                               linkedListTypes.add(type);
+                               continue;
+                       }
+                       if (SootUtil.isBinaryTree(type)) {
+                               binTypes.add(type);
+                               continue;
+                       }
+                       addToPetriNet(type);
+               }
+               SootUtil.createLinkedlistTransition(pNet, linkedListTypes);
+               SootUtil.createBinTransition(pNet, binTypes);
+
+//             System.out.println("-----------------------------------------------");
+//             for(Transition t : pNet.getTransitions()) {
+//                     String id = t.getId();
+//                     if(id.contains("_upper") || id.contains("_sdk")) continue;
+//                     System.out.println("Trans: " + t);
+//                     System.out.println("in: " + t.getPresetEdges());
+//                     System.out.println("out: " + t.getPostsetEdges());
+//             }
+               return this.pNet;
+       }
+       
+       public CustomType getInnerType(CustomType type) {
+               CustomMethod meth = new CustomMethod();
+               meth.setConstructor(false);
+               meth.setDeclaredClass("org.eclipse.jetty.http.HttpStatus.Code");
+               meth.setName("getMessage");
+               meth.setParams(new ArrayList<String>());
+               meth.setRetType("java.lang.String");
+               meth.setSignature("<org.eclipse.jetty.http.HttpStatus.Code: java.lang.String getMessage()>");
+               meth.setStaticMethod(false);
+               type.getMethods().add(meth);
+               type.setName("org.eclipse.jetty.http.HttpStatus.Code");
+               return type;
+       }
+       
+       public void addToPetriNet(CustomType type) {
+               if("org.eclipse.jetty.http.Code".equals(type.getName()))
+                       type = getInnerType(type);
+               
+               SootUtil.createPlace(pNet, type.getName());
+               for (CustomMethod meth : type.getMethods()) {
+                       String declClz = meth.getDeclaredClass();
+                       String api = meth.getSignature();
+                       if ("<org.eclipse.jetty.http.HttpStatus: org.eclipse.jetty.http.Code getCode(int)>".equals(api)) {
+                               api = "<org.eclipse.jetty.http.HttpStatus: org.eclipse.jetty.http.HttpStatus.Code getCode(int)>";
+                               meth.setRetType("org.eclipse.jetty.http.HttpStatus.Code");
+                       }
+                       if (pNet.containsTransition(api))
+                               continue;
+
+                       SootUtil.addHunterMethod(api, meth);
+                       SootUtil.createTransition(pNet, api);
+
+                       // constructor?
+                       if (meth.isConstructor() && meth.getParams().isEmpty()) {
+                               SootUtil.createPlace(pNet, declClz);
+                               pNet.createFlow("void", api);
+                               pNet.createFlow(api, declClz);
+                               continue;
+                       }
+
+                       List<String> params = new ArrayList<>();
+                       if (!meth.isConstructor() && !meth.isStaticMethod()) {
+                               // add receiver as the first param.
+                               params.add(declClz);
+                       }
+
+                       if (meth.isStaticMethod() && meth.getParams().isEmpty()) {
+                               params.add("void");
+                       }
+                       params.addAll(meth.getParams());
+                       assert !params.isEmpty();
+                       Map<String, Integer> map = SootUtil.sumTokens4Type(params);
+
+                       for (String param : map.keySet()) {
+                               Transition apiTran = pNet.getTransition(api);
+                               if (!apiTran.getPostsetEdges().isEmpty())
+                                       continue;
+                               int num = map.get(param);
+                               assert num > 0;
+                               SootUtil.createPlace(pNet, param);
+                               pNet.createFlow(param, api, num);
+                       }
+                       String retType = meth.getRetType();
+                       if (meth.isConstructor())
+                               retType = declClz;
+                       SootUtil.createPlace(pNet, retType);
+                       pNet.createFlow(api, retType);
+               }
+       }
+       
+       public void setPetriNet(PetriNet net) {
+               pNet = net;
+       }
+
+       public boolean isValid(String tgt) {
+               return (pNet.getPlaces().isEmpty() || pNet.getTransitions().isEmpty() || !pNet.containsPlace(tgt));
+       }
+       
+       public void printTrans() {
+               for (Transition t : pNet.getTransitions()) {
+                       System.out.println("Transition***:" + t + " args:" + t.getPreset() + " ret:" + t.getPostset());
+               }
+               System.out.println(pNet.getPlaces());
+       }
+
+       public void reset() {
+               srcPairs = null;
+               hasPath = false;
+               hasSketch = false;
+               hasInit = false;
+       }
+}