1 package edu.uci.eecs.specExtraction;
4 import java.util.ArrayList;
5 import java.util.regex.Matcher;
6 import java.util.regex.Pattern;
8 import edu.uci.eecs.specExtraction.SpecUtils.IntObj;
9 import edu.uci.eecs.specExtraction.SpecUtils.Primitive;
13 * This class is a subclass of Construct. It represents a complete global state
20 public class GlobalConstruct extends Construct {
21 public final ArrayList<VariableDeclaration> declState;
22 public final Code initState;
23 public final Code copyState;
24 public final Code clearState;
25 public final Code finalState;
26 public final Code printState;
27 public final ArrayList<CommutativityRule> commutativityRules;
29 // Whether the state declaration is empty
30 public final boolean emptyState;
31 // Whether we have auto-gen the state initialization code
32 public final boolean autoGenInitial;
33 // Whether we have auto-gen the state copying code
34 public final boolean autoGenCopy;
35 // Whether we have auto-gen the state clearing code
36 public final boolean autoGenClear;
37 // Whether we have auto-gen the state printing code
38 public final boolean autoGenPrint;
40 public GlobalConstruct(File file, int beginLineNum,
41 ArrayList<String> annotations) throws WrongAnnotationException {
42 super(file, beginLineNum);
43 declState = new ArrayList<VariableDeclaration>();
44 initState = new Code();
45 copyState = new Code();
46 clearState = new Code();
47 finalState = new Code();
48 printState = new Code();
49 commutativityRules = new ArrayList<CommutativityRule>();
51 processAnnotations(annotations);
53 emptyState = declState.isEmpty();
55 WrongAnnotationException.warning(file, beginLineNum,
56 "The state is empty. Make sure that's what you want!");
59 autoGenInitial = initState.isEmpty();
61 Code code = generateAutoInitalFunction();
62 initState.addLines(code);
65 autoGenCopy = copyState.isEmpty();
67 Code code = generateAutoCopyFunction();
68 copyState.addLines(code);
71 autoGenClear = clearState.isEmpty();
73 Code code = generateAutoClearFunction();
74 clearState.addLines(code);
77 autoGenPrint = printState.isEmpty();
79 Code code = generateAutoPrintFunction();
80 printState.addLines(code);
86 * This function will automatically generate the initial statements for
87 * supported types if the user has not defined the "@Initial" primitive
90 * @return The auto-generated state intialization statements
91 * @throws WrongAnnotationException
93 private Code generateAutoInitalFunction() throws WrongAnnotationException {
94 Code code = new Code();
95 if (emptyState) // Empty state should have empty initial function
97 for (VariableDeclaration decl : declState) {
98 String type = decl.type;
99 String name = decl.name;
101 if (type.equals("int") || type.equals("unsigned")
102 || type.equals("unsigned int")
103 || type.equals("int unsigned") || type.equals("double")
104 || type.equals("double") || type.equals("bool")) {
106 code.addLine(name + " = 0;");
107 } else if (type.equals("IntList") || type.equals("IntSet")
108 || type.equals("IntMap")) {
111 code.addLine(name + " = " + type + "();");
112 } else if (type.equals("IntList *") || type.equals("IntSet *")
113 || type.equals("IntMap *")) {
114 // Supported pointer types
116 String originalType = SpecUtils.trimSpace(type
118 code.addLine(name + " = new " + originalType + "();");
120 WrongAnnotationException
123 "You have types in the state declaration that we do not support auto-gen initial function.");
132 * This function will automatically generate the copy statements for
133 * supported types if the user has not defined the "@Copy" primitive
136 * @return The auto-generated state copy statements
137 * @throws WrongAnnotationException
139 private Code generateAutoCopyFunction() throws WrongAnnotationException {
140 Code code = new Code();
141 if (emptyState) // Empty state should have empty copy function
143 for (VariableDeclaration decl : declState) {
144 String type = decl.type;
145 String name = decl.name;
147 if (type.equals("int") || type.equals("unsigned")
148 || type.equals("unsigned int")
149 || type.equals("int unsigned") || type.equals("double")
150 || type.equals("double") || type.equals("bool")) {
152 code.addLine(SpecNaming.NewStateInst + "->" + name + " = "
153 + SpecNaming.OldStateInst + "->" + name + ";");
154 } else if (type.equals("IntList") || type.equals("IntSet")
155 || type.equals("IntMap")) {
157 // New->q = IntList(OLD->q);
158 code.addLine(SpecNaming.NewStateInst + "->" + name + " = "
159 + type + "(" + SpecNaming.OldStateInst + "->" + name
161 } else if (type.equals("IntList *") || type.equals("IntSet *")
162 || type.equals("IntMap *")) {
163 // Supported pointer types
164 // New->q = new IntList(*OLD->q);
165 String originalType = SpecUtils.trimSpace(type
167 code.addLine(SpecNaming.NewStateInst + "->" + name + " = new "
168 + originalType + "(*" + SpecNaming.OldStateInst + "->"
171 WrongAnnotationException
174 "You have types in the state declaration that we do not support auto-gen copy function.");
183 * This function will automatically generate the clear statements for
184 * supported types if the user has not defined the "@Clear" primitive
187 * @return The auto-generated state copy statements
188 * @throws WrongAnnotationException
190 private Code generateAutoClearFunction() throws WrongAnnotationException {
191 Code code = new Code();
192 if (emptyState) // Empty state should have empty copy function
195 // FIXME: Just try our best to generate recycling statements
196 for (VariableDeclaration decl : declState) {
197 String type = decl.type;
198 String name = decl.name;
199 if (type.equals("IntList *") || type.equals("IntSet *")
200 || type.equals("IntMap *")) {
201 // Supported pointer types
202 // if (stack) delete stack;
203 code.addLine("if (" + name + ") delete " + name + ";");
212 * This function will automatically generate the printing statements for
213 * supported types if the user has not defined the "@Print" primitive
216 * @return The auto-generated state printing statements
217 * @throws WrongAnnotationException
219 private Code generateAutoPrintFunction() throws WrongAnnotationException {
220 Code code = new Code();
221 if (emptyState) // Empty state should have empty printing function
223 for (VariableDeclaration decl : declState) {
224 String type = decl.type;
225 String name = decl.name;
226 code.addLines(SpecUtils.generatePrintStatement(type, name));
234 * Assert that the global state primitive is valid; if not, throws an
241 * The primitive that we have extracted earlier
242 * @throws WrongAnnotationException
244 private void assertValidPrimitive(File file, Primitive primitive)
245 throws WrongAnnotationException {
246 int lineNum = primitive.beginLineNum;
247 String name = primitive.name;
248 if (!name.equals(SpecNaming.DeclareState)
249 && !name.equals(SpecNaming.InitalState)
250 && !name.equals(SpecNaming.CopyState)
251 && !name.equals(SpecNaming.ClearState)
252 && !name.equals(SpecNaming.FinalState)
253 && !name.equals(SpecNaming.Commutativity)
254 && !name.equals(SpecNaming.PrintState)) {
255 WrongAnnotationException.err(file, lineNum, name
256 + " is NOT a valid CDSSpec global state primitive.");
262 * Given a "@DeclareState" primitive that has a list of strings of
263 * declarations, we initialize our local "declState" members.
266 * @throws WrongAnnotationException
268 private void processDeclState(Primitive primitive)
269 throws WrongAnnotationException {
270 for (int i = 0; i < primitive.contents.size(); i++) {
271 int lineNum = i + primitive.beginLineNum;
272 String declLine = primitive.contents.get(i);
273 VariableDeclaration tmp = new VariableDeclaration(file, lineNum,
281 * Given a "@DeclareState" primitive that has a list of strings of
282 * declarations, we initialize our local "declState" members.
285 * @throws WrongAnnotationException
287 private void processCommutativity(Primitive primitive)
288 throws WrongAnnotationException {
289 // Mathch commutativity rule
290 Pattern regexpCommute = Pattern
291 .compile("\\s*(\\w+)\\s*<->\\s*(\\w+)\\s*\\((.*)\\)\\s*$");
292 Matcher matcherCommute = regexpCommute.matcher("");
294 for (int i = 0; i < primitive.contents.size(); i++) {
295 // FIXME: Currently we only allow a one-line commutativity rule
296 int curLineNum = primitive.beginLineNum + i;
297 String line = primitive.contents.get(i);
298 matcherCommute.reset(line);
299 if (matcherCommute.find()) {
300 String method1 = matcherCommute.group(1);
301 String method2 = matcherCommute.group(2);
302 String code = matcherCommute.group(3);
303 String rule = SpecUtils.trimSpace(SpecUtils
304 .trimTrailingCommentSymbol(code));
305 commutativityRules.add(new CommutativityRule(method1, method2,
308 WrongAnnotationException
311 "The @Commutativity annotation should be: @Commutativity: Method1 <-> Method2 (condition)\n\t"
312 + "Problematic line: \"" + line + "\"");
314 // Done with processing the current commutativity
318 private void processAnnotations(ArrayList<String> annotations)
319 throws WrongAnnotationException {
320 IntObj curIdx = new IntObj(0);
321 Primitive primitive = null;
323 while ((primitive = SpecUtils.extractPrimitive(file, beginLineNum,
324 annotations, curIdx)) != null) {
325 String name = primitive.name;
326 assertValidPrimitive(file, primitive);
327 if (primitive.contents.size() == 0)
329 if (name.equals(SpecNaming.DeclareState)) {
330 processDeclState(primitive);
331 } else if (name.equals(SpecNaming.InitalState)) {
332 initState.addLines(primitive.contents);
333 } else if (name.equals(SpecNaming.CopyState)) {
334 copyState.addLines(primitive.contents);
335 } else if (name.equals(SpecNaming.ClearState)) {
336 clearState.addLines(primitive.contents);
337 } else if (name.equals(SpecNaming.FinalState)) {
338 finalState.addLines(primitive.contents);
339 } else if (name.equals(SpecNaming.PrintState)) {
340 printState.addLines(primitive.contents);
341 } else if (name.equals(SpecNaming.Commutativity)) {
342 processCommutativity(primitive);
347 public String toString() {
348 StringBuilder sb = new StringBuilder("");
349 sb.append(super.toString() + "\n");
350 sb.append("@DeclareState:\n");
351 sb.append(declState);
353 sb.append("@InitState:\n");
354 sb.append(initState);
355 if (!printState.isEmpty()) {
356 sb.append("@Print:\n");
357 sb.append(printState);
360 for (int i = 0; i < commutativityRules.size(); i++) {
361 sb.append("@Commutativity: " + commutativityRules + "\n");
363 return sb.toString();