00001 package edu.ksu.cis.bandera.specification;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 import java.util.*;
00041 import java.lang.reflect.*;
00042 import java.io.*;
00043 import ca.mcgill.sable.soot.*;
00044 import edu.ksu.cis.bandera.specification.analysis.*;
00045 import edu.ksu.cis.bandera.specification.datastructure.*;
00046 import edu.ksu.cis.bandera.specification.node.*;
00047 import edu.ksu.cis.bandera.specification.pattern.*;
00048 import edu.ksu.cis.bandera.specification.pattern.datastructure.*;
00049 import edu.ksu.cis.bandera.specification.predicate.node.PPropositionDefinition;
00050 import edu.ksu.cis.bandera.specification.predicate.datastructure.*;
00051 import edu.ksu.cis.bandera.annotation.*;
00052 import edu.ksu.cis.bandera.jext.*;
00053 import edu.ksu.cis.bandera.jjjc.*;
00054 import edu.ksu.cis.bandera.util.*;
00055 import gov.nasa.arc.ase.jpf.tools.*;
00056
00057 public class JPFLTLCompiler extends DepthFirstAdapter {
00058 private String tempDir = ".";
00059 private TemporalLogicProperty tlp;
00060 private Hashtable ptab;
00061 private List qList;
00062 private Pattern pattern;
00063 private Iterator patternParamIterator;
00064 private String currentValue = null;
00065 private Hashtable patternNodeTable = new Hashtable();
00066 private Hashtable patternNameTable = new Hashtable();
00067 private boolean useConstraint;
00068
00069
00070
00071
00072
00073
00074 public JPFLTLCompiler(String dir, TemporalLogicProperty tl, List q)
00075 {
00076 if (dir != null) tempDir = dir;
00077 if (tl == null) throw new RuntimeException("Temporal Logic Property may NOT be null!!");
00078 tlp = tl; qList = q;
00079 }
00080 public void caseABinaryExp(ABinaryExp node)
00081 {
00082 node.getLeft().apply(this);
00083 String leftValue = currentValue;
00084 node.getRight().apply(this);
00085 String rightValue = currentValue;
00086
00087 PBinOp binOp = node.getBinOp();
00088 if (binOp instanceof AAndBinOp) {
00089 currentValue = "(" + leftValue + " /\\ " + rightValue + ")";
00090 } else if (binOp instanceof AOrBinOp) {
00091 currentValue = "(" + leftValue + " \\/ " + rightValue + ")";
00092 } else {
00093 currentValue = "(" + leftValue + " -> " + rightValue + ")";
00094 }
00095 }
00096 public void caseAComplementExp(AComplementExp node)
00097 {
00098 node.getExp().apply(this);
00099 if (currentValue == null) currentValue = "(0 != 0)";
00100 currentValue = "!"+currentValue;
00101 }
00102 public void caseAExpWord(AExpWord node) {
00103 node.getExp().apply(this);
00104
00105 try {
00106 String id = (String) patternParamIterator.next();
00107 if (currentValue == null) currentValue = "(0 == 0)";
00108 patternNameTable.put(id, currentValue);
00109 } catch (Exception e)
00110 {
00111 System.out.println("WARNING: Unexpected pattern end!");
00112 }
00113 }
00114 public void caseAPredicateExp(APredicateExp node) {
00115 String temp = (String) patternNodeTable.get(node);
00116
00117 if (temp == null)
00118 {
00119 System.out.println("WARNING: Pattern table of "+node+" yields null!");
00120 temp = "(0 == 0)";
00121 }
00122 currentValue = temp;
00123 }
00124 public void compile()
00125 {
00126 try {
00127 String classpath = System.getProperty("java.class.path");
00128 ptab = tlp.getPredicatesTable();
00129 pattern = PatternSaverLoader.getPattern(tlp.getPatternName(), tlp.getPatternScope());
00130 patternParamIterator = pattern.getParametersOccurenceOrder().iterator();
00131 LinkedList processedPreds = new LinkedList();
00132
00133
00134 for (Enumeration e = ptab.keys(); e.hasMoreElements(); )
00135 {
00136 APredicateExp n = (APredicateExp) e.nextElement();
00137
00138
00139 Predicate pred = (Predicate) ptab.get(n);
00140
00141
00142 String className = pred.getType().getFullyQualifiedName();
00143 Class theClass = null;
00144 try {
00145 theClass = FileClassLoader.load(className);
00146 } catch (Exception exx)
00147 {
00148 throw new RuntimeException("Can't find class " + className);
00149 }
00150 java.lang.reflect.Method theMethod = null;
00151 Annotation ann = pred.getAnnotation();
00152
00153
00154 if (ann instanceof MethodDeclarationAnnotation)
00155 {
00156 theMethod = getMatchedMethod(theClass, ((MethodDeclarationAnnotation) ann).getSootMethod());
00157 if (theMethod == null) throw new RuntimeException("Method not found!");
00158 }
00159
00160
00161
00162 PPropositionDefinition node = (PPropositionDefinition) pred.getNode();
00163 String predFileName = className;
00164 if (theMethod != null) predFileName += ("$"+theMethod.getName());
00165 predFileName += ("$" + node.getId().getText());
00166
00167
00168 if (!processedPreds.contains(predFileName))
00169 {
00170 try {
00171
00172 node.apply(new Translation(theClass, theMethod, tempDir));
00173
00174
00175 BanderaUtil.runJavac(classpath, tempDir + File.separator + predFileName + ".java");
00176
00177
00178 processedPreds.add(predFileName);
00179 } catch (Exception exx)
00180 {
00181 throw new RuntimeException("Error: " + exx.getMessage());
00182 }
00183 }
00184
00185
00186 if (n.getArgs() != null)
00187 {
00188 Hashtable qtab = tlp.getQuantifiersTable();
00189 String params = "";
00190
00191 PArgs predArg;
00192
00193 do {
00194 predArg = n.getArgs();
00195
00196 String argId;
00197 if (predArg instanceof AArgsArgs)
00198 {
00199 AArgsArgs multiArgs = (AArgsArgs) predArg;
00200 predArg = multiArgs.getArgs();
00201 argId = multiArgs.getId().toString();
00202 } else if (predArg instanceof AIdArgs)
00203 {
00204 AIdArgs singleArg = (AIdArgs) predArg;
00205 argId = singleArg.getId().toString();
00206 } else {
00207 throw new RuntimeException("Unknown predicate parameter: "+predArg);
00208 }
00209
00210 try {
00211 QuantifiedVariable qv = (QuantifiedVariable) qtab.get(argId.trim());
00212
00213 argId = getQualifiedNameForQv(qv.getName());
00214
00215 } catch (Exception exx)
00216 {
00217 exx.printStackTrace();
00218 throw new RuntimeException("Parameter "+argId+" is not in the table:\n"+exx.getMessage());
00219 }
00220 if (!"".equals(params)) params = argId + ", "+ params; else params = argId;
00221 } while (predArg instanceof AArgsArgs);
00222
00223
00224 System.out.println(predFileName + "(" + params + ") added");
00225 patternNodeTable.put(n, "\"" + predFileName + "(" + params + ")\"");
00226 } else
00227 {
00228
00229 patternNodeTable.put(n, "\"" + predFileName + "\"");
00230 }
00231 }
00232
00233
00234
00235
00236
00237 tlp.getNode().apply(this);
00238
00239
00240 if (qList != null && qList.size() > 0)
00241 {
00242 String lineSep = System.getProperty("line.separator");
00243
00244 StringBuffer selectbuf = new StringBuffer();
00245
00246
00247 selectbuf.append("import gov.nasa.arc.ase.jpf.jvm.State;" + lineSep);
00248 selectbuf.append("import gov.nasa.arc.ase.jpf.jvm.Reference;" + lineSep);
00249 selectbuf.append("import gov.nasa.arc.ase.jpf.jvm.Thread;" + lineSep + lineSep);
00250 selectbuf.append("public class Selected {" + lineSep);
00251 selectbuf.append(" public static boolean evaluate(State state, Reference _this) {" + lineSep);
00252 selectbuf.append(" return _this != null");
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 selectbuf.append(";" + lineSep);
00266
00267
00268
00269
00270 selectbuf.append(" }"+lineSep);
00271 selectbuf.append("}" + lineSep);
00272
00273
00274 String completeName = tempDir + File.separator + "Selected.java";
00275 System.out.println(completeName);
00276
00277 try {
00278 PrintStream javaPrint = new PrintStream(new FileOutputStream(new File(completeName)));
00279 javaPrint.print(selectbuf.toString());
00280 javaPrint.close();
00281
00282
00283 BanderaUtil.runJavac(classpath, completeName);
00284 } catch (IOException ex)
00285 {
00286 throw new RuntimeException("Cannot create file '" + completeName + "'");
00287 }
00288 }
00289 } catch (Exception suckers)
00290 {
00291 suckers.printStackTrace();
00292 }
00293 }
00294 public String getFormula(String mapping)
00295 {
00296 if ("LTL".equalsIgnoreCase(mapping))
00297 return getLTLFormula();
00298
00299
00300 throw new RuntimeException("Mapping to " + mapping + " is currently not supported");
00301 }
00302 private String getLTLFormula()
00303 {
00304
00305 String ltlFormula;
00306
00307 try {
00308 ltlFormula = pattern.expandMapping("ltl", patternNameTable);
00309 } catch (Exception e)
00310 {
00311 throw new RuntimeException("Pattern mapping not supported!\nTable:\n"+patternNameTable);
00312 }
00313
00314
00315
00316
00317 if (qList != null && qList.size() > 0)
00318 {
00319 StringBuffer sel = new StringBuffer();
00320 for (Iterator qi = qList.iterator(); qi.hasNext(); )
00321 {
00322 QuantifierClassPair qcp = (QuantifierClassPair) qi.next();
00323 sel.append("Selected("+qcp.getClassName()+"."+qcp.getFieldName()+")");
00324
00325 if (qi.hasNext()) sel.append(" && ");
00326 }
00327 String selected = "\"" + sel.toString() + "\"";
00328 ltlFormula = "(!"+selected+" U ("+selected+" /\\ (" + ltlFormula + "))) \\/ []!"+selected;
00329 }
00330
00331
00332 int lastpos = 0;
00333
00334
00335 do {
00336 lastpos = ltlFormula.indexOf("&&", lastpos);
00337 if (lastpos != -1)
00338 ltlFormula = ltlFormula.substring(0,lastpos) + "/\\" + ltlFormula.substring(lastpos+2);
00339 } while (lastpos != -1);
00340
00341 lastpos = 0;
00342
00343
00344 do {
00345 lastpos = ltlFormula.indexOf("||", lastpos);
00346 if (lastpos != -1)
00347 ltlFormula = ltlFormula.substring(0,lastpos) + "\\/" + ltlFormula.substring(lastpos+2);
00348 } while (lastpos != -1);
00349
00350
00351 return ltlFormula;
00352 }
00353 private Method getMatchedMethod(Class theClass, SootMethod sm)
00354 {
00355 Method[] methods = theClass.getDeclaredMethods();
00356
00357 int max = methods.length;
00358 String name = sm.getName();
00359 if (name == null) throw new RuntimeException("Error! Bogus Soot Method!");
00360
00361 for (int i = 0; i < max; i++)
00362 {
00363 Method m = methods[i];
00364 if (!name.equals(m.getName())) continue;
00365 Class[] params = m.getParameterTypes();
00366 int maxParams = params.length;
00367 if (sm.getParameterCount() != maxParams) continue;
00368 boolean found = true;
00369
00370 for (int j = 0; j < maxParams; j++)
00371 {
00372 Class p1 = params[j];
00373 String sig = getTypeString(p1);
00374 Type t1 = sm.getParameterType(i);
00375 if (!sig.equals(t1.toString().trim()))
00376 {
00377 found = false; break;
00378 }
00379 }
00380 if (found) return m;
00381 }
00382
00383 return null;
00384 }
00385 private String getQualifiedNameForQv(String v)
00386 {
00387 for (Iterator i = qList.iterator(); i.hasNext(); )
00388 {
00389 QuantifierClassPair qcp = (QuantifierClassPair) i.next();
00390 if (qcp.getFieldName().equals("quantification$"+v))
00391 return qcp.toString();
00392 }
00393 return null;
00394 }
00395 private String getTypeString(Class c)
00396 {
00397 if (c.isArray()) return getTypeString(c.getComponentType())+"[]";
00398 return c.getName();
00399 }
00400 }