00001 package edu.ksu.cis.bandera.specification.assertion;
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 import edu.ksu.cis.bandera.jjjc.symboltable.*;
00036 import edu.ksu.cis.bandera.annotation.*;
00037 import edu.ksu.cis.bandera.jjjc.analysis.*;
00038 import edu.ksu.cis.bandera.jjjc.node.*;
00039 import edu.ksu.cis.bandera.jjjc.*;
00040 import java.util.*;
00041 import edu.ksu.cis.bandera.specification.assertion.datastructure.*;
00042 public class AssertionProcessor extends DepthFirstAdapter {
00043 private static Hashtable assertionTable;
00044 private static AssertionProcessor processor = new AssertionProcessor();
00045 private static HashSet preSet;
00046 private static Hashtable locationTable;
00047 private static HashSet postSet;
00048 private static PType type;
00049 private static boolean hasRet;
00050 private static Hashtable modifiedMethodTable;
00051 private static Annotation currentAnnotation;
00052
00053
00054
00055
00056
00057 private ca.mcgill.sable.util.List buildArgumentList(Assertion a) {
00058 PExp exp;
00059
00060 if (((Collection) assertionTable.get(a)).size() == 0) {
00061 exp = (PExp) a.getConstraint().clone();
00062 } else {
00063 Iterator i = ((Collection) assertionTable.get(a)).iterator();
00064 if (a instanceof PreAssertion) {
00065 exp = new ABinaryExp((PExp) a.getConstraint().clone(), new AOrBinaryOperator(new TOr()), (PExp) i.next());
00066 while (i.hasNext()) {
00067 exp = new ABinaryExp(exp, new AOrBinaryOperator(new TOr()), (PExp) i.next());
00068 }
00069 } else {
00070 exp = new ABinaryExp((PExp) a.getConstraint().clone(), new AAndBinaryOperator(new TAnd()), (PExp) i.next());
00071 while (i.hasNext()) {
00072 exp = new ABinaryExp(exp, new AAndBinaryOperator(new TAnd()), (PExp) i.next());
00073 }
00074 }
00075 }
00076
00077 ca.mcgill.sable.util.LinkedList result = new ca.mcgill.sable.util.LinkedList();
00078 result.addLast(exp);
00079 return result;
00080 }
00081
00082
00083
00084
00085 public void caseABlockMethodBody(ABlockMethodBody node) {
00086 ca.mcgill.sable.util.LinkedList list = ((ABlock) node.getBlock()).getBlockedStmt();
00087
00088 boolean isSynchronized = false;
00089 boolean isStatic = false;
00090
00091 Method m = ((MethodDeclarationAnnotation) currentAnnotation).getMethod();
00092 isSynchronized = CompilationManager.isSynchTransformed(currentAnnotation.getNode());
00093 isStatic = java.lang.reflect.Modifier.isStatic(m.getModifiers());
00094
00095 if (isSynchronized) {
00096 if (isStatic) {
00097 ATryStmt ts = (ATryStmt) ((AStmtBlockedStmt) list.iterator().next()).getStmt();
00098 list = ((ABlock) ts.getBlock()).getBlockedStmt();
00099 ASynchronizedStmt ss = (ASynchronizedStmt) ((AStmtBlockedStmt) list.iterator().next()).getStmt();
00100 list = ((ABlock) ss.getBlock()).getBlockedStmt();
00101 } else {
00102 ASynchronizedStmt ss = (ASynchronizedStmt) ((AStmtBlockedStmt) list.iterator().next()).getStmt();
00103 list = ((ABlock) ss.getBlock()).getBlockedStmt();
00104 }
00105 }
00106
00107 for (Iterator i = preSet.iterator(); i.hasNext();) {
00108 PreAssertion a = (PreAssertion) i.next();
00109 PName name = new AQualifiedName(new ASimpleName(new TId("Bandera")), new TDot(), new TId("assert"));
00110 PExp exp = new ANameMethodInvocationExp(name, new TLPar(), buildArgumentList(a), new TRPar());
00111 PStmt stmt = new AExpStmt(exp, new TSemicolon());
00112 list.addFirst(new AStmtBlockedStmt(stmt));
00113 }
00114
00115 hasRet = false;
00116
00117 for (Iterator i = postSet.iterator(); i.hasNext();) {
00118 PostAssertion a = (PostAssertion) i.next();
00119 if (a.hasRet()) {
00120 hasRet = true;
00121 break;
00122 }
00123 }
00124
00125 if (hasRet) {
00126 ca.mcgill.sable.util.LinkedList varList = new ca.mcgill.sable.util.LinkedList();
00127 varList.addFirst(new AIdVariableDeclarator(new AVariableDeclaratorId(new TId("$ret"), new ca.mcgill.sable.util.LinkedList())));
00128 ALocalVariableDeclaration decl = new ALocalVariableDeclaration(new ca.mcgill.sable.util.LinkedList(),
00129 type, varList);
00130 list.addFirst(new ALocalVariableDeclarationInBlockedStmt(decl, new TSemicolon()));
00131 }
00132
00133 if (type == null) {
00134 PStmt lastStmt = ((AStmtBlockedStmt) list.getLast()).getStmt();
00135 if (!(lastStmt instanceof AReturnStmt)) {
00136 ca.mcgill.sable.util.LinkedList list2 = new ca.mcgill.sable.util.LinkedList();
00137 for (Iterator i = postSet.iterator(); i.hasNext();) {
00138 PostAssertion a = (PostAssertion) i.next();
00139 PName name = new AQualifiedName(new ASimpleName(new TId("Bandera")), new TDot(), new TId("assert"));
00140 PExp exp2 = new ANameMethodInvocationExp(name, new TLPar(), buildArgumentList(a), new TRPar());
00141 PStmt stmt = new AExpStmt(exp2, new TSemicolon());
00142 list2.addLast(new AStmtBlockedStmt(stmt));
00143 }
00144
00145 ABlock block = new ABlock(new TLBrace(), list2, new TRBrace());
00146 list.addLast(new AStmtBlockedStmt(new ABlockStmt(block)));
00147 }
00148 }
00149
00150 super.caseABlockMethodBody(node);
00151 }
00152
00153
00154
00155
00156 public void caseABreakStmt(ABreakStmt node) {
00157 if (node.getId() != null) {
00158 String label = node.getId().toString().trim();
00159 if (locationTable.get(label) != null) {
00160 node.getId().setText("assertion$" + label);
00161 }
00162 }
00163 super.caseABreakStmt(node);
00164 }
00165
00166
00167
00168
00169 public void caseAConstructorBody(AConstructorBody node) {
00170 ca.mcgill.sable.util.LinkedList list = node.getBlockedStmt();
00171 Method m = ((ConstructorDeclarationAnnotation) currentAnnotation).getConstructor();
00172 if (preSet.size() > 0) {
00173 ca.mcgill.sable.util.LinkedList list2 = new ca.mcgill.sable.util.LinkedList();
00174 for (Iterator i = preSet.iterator(); i.hasNext();) {
00175 PreAssertion a = (PreAssertion) i.next();
00176 PName name = new AQualifiedName(new ASimpleName(new TId("Bandera")), new TDot(), new TId("assert"));
00177 PExp exp = new ANameMethodInvocationExp(name, new TLPar(), buildArgumentList(a), new TRPar());
00178 PStmt stmt = new AExpStmt(exp, new TSemicolon());
00179 list2.addLast(new AStmtBlockedStmt(stmt));
00180 }
00181 ABlock block = new ABlock(new TLBrace(), list2, new TRBrace());
00182 list.addFirst(new AStmtBlockedStmt(new ABlockStmt(block)));
00183 }
00184 PStmt lastStmt = ((AStmtBlockedStmt) list.getLast()).getStmt();
00185 if (!(lastStmt instanceof AReturnStmt)) {
00186 if (postSet.size() > 0) {
00187 ca.mcgill.sable.util.LinkedList list2 = new ca.mcgill.sable.util.LinkedList();
00188 for (Iterator i = postSet.iterator(); i.hasNext();) {
00189 PostAssertion a = (PostAssertion) i.next();
00190 PName name = new AQualifiedName(new ASimpleName(new TId("Bandera")), new TDot(), new TId("assert"));
00191 PExp exp2 = new ANameMethodInvocationExp(name, new TLPar(), buildArgumentList(a), new TRPar());
00192 PStmt stmt = new AExpStmt(exp2, new TSemicolon());
00193 list2.addLast(new AStmtBlockedStmt(stmt));
00194 }
00195 ABlock block = new ABlock(new TLBrace(), list2, new TRBrace());
00196 list.addLast(new AStmtBlockedStmt(new ABlockStmt(block)));
00197 }
00198 }
00199 super.caseAConstructorBody(node);
00200 }
00201
00202
00203
00204
00205 public void caseAConstructorDeclaration(AConstructorDeclaration node) {
00206 AConstructorDeclaration newNode = (AConstructorDeclaration) node.clone();
00207 modifiedMethodTable.put(node, newNode);
00208 super.caseAConstructorDeclaration(newNode);
00209 }
00210
00211
00212
00213
00214 public void caseAContinueStmt(AContinueStmt node) {
00215 if (node.getId() != null) {
00216 String label = node.getId().toString().trim();
00217 if (locationTable.get(label) != null) {
00218 node.getId().setText("assertion$" + label);
00219 }
00220 }
00221 }
00222
00223
00224
00225
00226 public void caseALabelStmt(ALabelStmt node) {
00227 String label = node.getId().toString().trim();
00228 if (locationTable.get(label) != null) {
00229 ca.mcgill.sable.util.LinkedList list = new ca.mcgill.sable.util.LinkedList();
00230
00231 for (Iterator i = ((Collection) locationTable.get(label)).iterator(); i.hasNext();) {
00232 LocationAssertion a = (LocationAssertion) i.next();
00233 PName name = new AQualifiedName(new ASimpleName(new TId("Bandera")), new TDot(), new TId("assert"));
00234 PExp exp = new ANameMethodInvocationExp(name, new TLPar(), buildArgumentList(a), new TRPar());
00235 PStmt stmt = new AExpStmt(exp, new TSemicolon());
00236 list.addFirst(new AStmtBlockedStmt(stmt));
00237 }
00238
00239 ABlock block = new ABlock(new TLBrace(), list, new TRBrace());
00240 PStmt stmt = new ABlockStmt(block);
00241
00242 list = new ca.mcgill.sable.util.LinkedList();
00243 list.addLast(new AStmtBlockedStmt(stmt));
00244 block = new ABlock(new TLBrace(), list, new TRBrace());
00245
00246 stmt = new ALabelStmt(new TId("assertion$" + label), new TColon(), block);
00247
00248 block = (ABlock) node.parent().parent();
00249 list = block.getBlockedStmt();
00250 int index = list.indexOf(node.parent());
00251 list.add(index, new AStmtBlockedStmt(stmt));
00252 }
00253 super.caseALabelStmt(node);
00254 }
00255
00256
00257
00258
00259 public void caseAMethodDeclaration(AMethodDeclaration node) {
00260 AMethodDeclaration newNode = (AMethodDeclaration) node.clone();
00261 modifiedMethodTable.put(node, newNode);
00262 super.caseAMethodDeclaration(newNode);
00263
00264 }
00265
00266
00267
00268
00269 public void caseAReturnStmt(AReturnStmt node) {
00270 if (postSet.size() > 0) {
00271 ca.mcgill.sable.util.LinkedList list = new ca.mcgill.sable.util.LinkedList();
00272
00273 PExp exp = null;
00274 if (type != null) {
00275 exp = (PExp) node.getExp().clone();
00276 }
00277
00278 if (hasRet) {
00279 exp = new AAssignmentExp(new ANameLeftHandSide(new ASimpleName(new TId("$ret"))), new AAssignAssignmentOperator(new TAssign()), exp);
00280 list.addFirst(new AStmtBlockedStmt(new AExpStmt(exp, new TSemicolon())));
00281 exp = new ANameExp(new ASimpleName(new TId("$ret")));
00282 }
00283
00284 for (Iterator i = postSet.iterator(); i.hasNext();) {
00285 PostAssertion a = (PostAssertion) i.next();
00286 PName name = new AQualifiedName(new ASimpleName(new TId("Bandera")), new TDot(), new TId("assert"));
00287 PExp exp2 = new ANameMethodInvocationExp(name, new TLPar(), buildArgumentList(a), new TRPar());
00288 PStmt stmt = new AExpStmt(exp2, new TSemicolon());
00289 list.addLast(new AStmtBlockedStmt(stmt));
00290 }
00291
00292 list.addLast(new AStmtBlockedStmt(new AReturnStmt(node.getReturn(), exp, node.getSemicolon())));
00293
00294 ABlock block = new ABlock(new TLBrace(), list, new TRBrace());
00295 node.replaceBy(new ABlockStmt(block));
00296 }
00297 super.caseAReturnStmt(node);
00298 }
00299
00300
00301
00302
00303 public void caseATypedMethodHeader(ATypedMethodHeader node) {
00304 type = (PType) node.getType().clone();
00305 super.caseATypedMethodHeader(node);
00306 }
00307
00308
00309
00310
00311
00312 public static Hashtable process(Hashtable assertionTable) {
00313 modifiedMethodTable = new Hashtable();
00314 AssertionProcessor.assertionTable = assertionTable;
00315
00316 HashSet methodAnnotationSet = new HashSet();
00317
00318 for (Enumeration e = assertionTable.keys(); e.hasMoreElements();) {
00319 Annotation a = ((Assertion) e.nextElement()).getAnnotation();
00320
00321 if (a instanceof LabeledStmtAnnotation) {
00322 a = CompilationManager.getAnnotationManager().getMethodAnnotationContainingAnnotation(a);
00323 }
00324
00325 methodAnnotationSet.add(a);
00326 }
00327
00328
00329 StringBuffer sb = new StringBuffer();
00330 for (Iterator i = methodAnnotationSet.iterator(); i.hasNext();) {
00331 preSet = new HashSet();
00332 locationTable = new Hashtable();
00333 postSet = new HashSet();
00334 Annotation a = (Annotation) i.next();
00335
00336 for (Enumeration e = assertionTable.keys(); e.hasMoreElements();) {
00337 Assertion as = (Assertion) e.nextElement();
00338 if (as.getExceptions().size() > 0) {
00339 sb.append("In '" + as + "':\n");
00340 for (Iterator j = as.getExceptions().iterator(); j.hasNext();) {
00341 sb.append("* " + ((Exception) j.next()).getMessage() + "\n");
00342 }
00343 }
00344 Annotation a2 = as.getAnnotation();
00345 if (a2 instanceof LabeledStmtAnnotation) {
00346 a2 = CompilationManager.getAnnotationManager().getMethodAnnotationContainingAnnotation(a2);
00347 }
00348 if (a == a2) {
00349 if (as instanceof PreAssertion) {
00350 preSet.add(as);
00351 } else if (as instanceof LocationAssertion) {
00352 String label = ((LocationAssertion) as).getLabel();
00353 if (locationTable.get(label) == null) {
00354 locationTable.put(label, new HashSet());
00355 }
00356 ((HashSet) locationTable.get(label)).add(as);
00357 } else {
00358 postSet.add(as);
00359 }
00360 }
00361 }
00362
00363 String s = sb.toString();
00364 if (s.length() != 0)
00365 throw new RuntimeException(s.substring(0, s.length() - 1));
00366
00367 type = null;
00368 currentAnnotation = a;
00369 a.getNode().apply(processor);
00370 }
00371 return modifiedMethodTable;
00372 }
00373 }