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!");
57 // Add a fake state declaration
58 declState.add(new VariableDeclaration("int", "FakeState"));
61 autoGenInitial = initState.isEmpty();
63 Code code = generateAutoInitalFunction();
64 initState.addLines(code);
67 autoGenCopy = copyState.isEmpty();
69 Code code = generateAutoCopyFunction();
70 copyState.addLines(code);
73 autoGenClear = clearState.isEmpty();
75 Code code = generateAutoClearFunction();
76 clearState.addLines(code);
79 autoGenPrint = printState.isEmpty();
81 Code code = generateAutoPrintFunction();
82 printState.addLines(code);
88 * This function will automatically generate the initial statements for
89 * supported types if the user has not defined the "@Initial" primitive
92 * @return The auto-generated state intialization statements
93 * @throws WrongAnnotationException
95 private Code generateAutoInitalFunction() throws WrongAnnotationException {
96 Code code = new Code();
97 if (emptyState) // Empty state should have empty initial function
99 for (VariableDeclaration decl : declState) {
100 String type = decl.type;
101 String name = decl.name;
103 if (type.equals("int") || type.equals("unsigned")
104 || type.equals("unsigned int")
105 || type.equals("int unsigned") || type.equals("double")
106 || type.equals("double") || type.equals("bool")) {
108 code.addLine(name + " = 0;");
109 } else if (type.equals("IntList") || type.equals("IntSet")
110 || type.equals("IntMap")) {
113 code.addLine(name + " = " + type + "();");
114 } else if (type.equals("IntList *") || type.equals("IntSet *")
115 || type.equals("IntMap *")) {
116 // Supported pointer types
118 String originalType = SpecUtils.trimSpace(type
120 code.addLine(name + " = new " + originalType + "();");
122 WrongAnnotationException
125 "You have types in the state declaration that we do not support auto-gen initial function.");
134 * This function will automatically generate the copy statements for
135 * supported types if the user has not defined the "@Copy" primitive
138 * @return The auto-generated state copy statements
139 * @throws WrongAnnotationException
141 private Code generateAutoCopyFunction() throws WrongAnnotationException {
142 Code code = new Code();
143 if (emptyState) // Empty state should have empty copy function
145 for (VariableDeclaration decl : declState) {
146 String type = decl.type;
147 String name = decl.name;
149 if (type.equals("int") || type.equals("unsigned")
150 || type.equals("unsigned int")
151 || type.equals("int unsigned") || type.equals("double")
152 || type.equals("double") || type.equals("bool")) {
154 code.addLine(SpecNaming.NewStateInst + "->" + name + " = "
155 + SpecNaming.OldStateInst + "->" + name + ";");
156 } else if (type.equals("IntList") || type.equals("IntSet")
157 || type.equals("IntMap")) {
159 // New->q = IntList(OLD->q);
160 code.addLine(SpecNaming.NewStateInst + "->" + name + " = "
161 + type + "(" + SpecNaming.OldStateInst + "->" + name
163 } else if (type.equals("IntList *") || type.equals("IntSet *")
164 || type.equals("IntMap *")) {
165 // Supported pointer types
166 // New->q = new IntList(*OLD->q);
167 String originalType = SpecUtils.trimSpace(type
169 code.addLine(SpecNaming.NewStateInst + "->" + name + " = new "
170 + originalType + "(*" + SpecNaming.OldStateInst + "->"
173 WrongAnnotationException
176 "You have types in the state declaration that we do not support auto-gen copy function.");
185 * This function will automatically generate the clear statements for
186 * supported types if the user has not defined the "@Clear" primitive
189 * @return The auto-generated state copy statements
190 * @throws WrongAnnotationException
192 private Code generateAutoClearFunction() throws WrongAnnotationException {
193 Code code = new Code();
194 if (emptyState) // Empty state should have empty copy function
197 // FIXME: Just try our best to generate recycling statements
198 for (VariableDeclaration decl : declState) {
199 String type = decl.type;
200 String name = decl.name;
201 if (type.equals("IntList *") || type.equals("IntSet *")
202 || type.equals("IntMap *")) {
203 // Supported pointer types
204 // if (stack) delete stack;
205 code.addLine("if (" + name + ") delete " + name + ";");
214 * This function will automatically generate the printing statements for
215 * supported types if the user has not defined the "@Print" primitive
218 * @return The auto-generated state printing statements
219 * @throws WrongAnnotationException
221 private Code generateAutoPrintFunction() throws WrongAnnotationException {
222 Code code = new Code();
223 if (emptyState) // Empty state should have empty printing function
225 for (VariableDeclaration decl : declState) {
226 String type = decl.type;
227 String name = decl.name;
228 code.addLines(SpecUtils.generatePrintStatement(type, name));
236 * Assert that the global state primitive is valid; if not, throws an
243 * The primitive that we have extracted earlier
244 * @throws WrongAnnotationException
246 private void assertValidPrimitive(File file, Primitive primitive)
247 throws WrongAnnotationException {
248 int lineNum = primitive.beginLineNum;
249 String name = primitive.name;
250 if (!name.equals(SpecNaming.DeclareState)
251 && !name.equals(SpecNaming.InitalState)
252 && !name.equals(SpecNaming.CopyState)
253 && !name.equals(SpecNaming.ClearState)
254 && !name.equals(SpecNaming.FinalState)
255 && !name.equals(SpecNaming.Commutativity)
256 && !name.equals(SpecNaming.PrintState)) {
257 WrongAnnotationException.err(file, lineNum, name
258 + " is NOT a valid CDSSpec global state primitive.");
264 * Given a "@DeclareState" primitive that has a list of strings of
265 * declarations, we initialize our local "declState" members.
268 * @throws WrongAnnotationException
270 private void processDeclState(Primitive primitive)
271 throws WrongAnnotationException {
272 for (int i = 0; i < primitive.contents.size(); i++) {
273 int lineNum = i + primitive.beginLineNum;
274 String declLine = primitive.contents.get(i);
275 VariableDeclaration tmp = new VariableDeclaration(file, lineNum,
283 * Given a "@DeclareState" primitive that has a list of strings of
284 * declarations, we initialize our local "declState" members.
287 * @throws WrongAnnotationException
289 private void processCommutativity(Primitive primitive)
290 throws WrongAnnotationException {
291 // Mathch commutativity rule
292 Pattern regexpCommute = Pattern
293 .compile("\\s*(\\w+)\\s*<->\\s*(\\w+)\\s*\\((.*)\\)\\s*$");
294 Matcher matcherCommute = regexpCommute.matcher("");
296 for (int i = 0; i < primitive.contents.size(); i++) {
297 // FIXME: Currently we only allow a one-line commutativity rule
298 int curLineNum = primitive.beginLineNum + i;
299 String line = primitive.contents.get(i);
300 matcherCommute.reset(line);
301 if (matcherCommute.find()) {
302 String method1 = matcherCommute.group(1);
303 String method2 = matcherCommute.group(2);
304 String code = matcherCommute.group(3);
305 String rule = SpecUtils.trimSpace(SpecUtils
306 .trimTrailingCommentSymbol(code));
307 commutativityRules.add(new CommutativityRule(method1, method2,
310 WrongAnnotationException
313 "The @Commutativity annotation should be: @Commutativity: Method1 <-> Method2 (condition)\n\t"
314 + "Problematic line: \"" + line + "\"");
316 // Done with processing the current commutativity
320 private void processAnnotations(ArrayList<String> annotations)
321 throws WrongAnnotationException {
322 IntObj curIdx = new IntObj(0);
323 Primitive primitive = null;
325 while ((primitive = SpecUtils.extractPrimitive(file, beginLineNum,
326 annotations, curIdx)) != null) {
327 String name = primitive.name;
328 assertValidPrimitive(file, primitive);
329 if (primitive.contents.size() == 0)
331 if (name.equals(SpecNaming.DeclareState)) {
332 processDeclState(primitive);
333 } else if (name.equals(SpecNaming.InitalState)) {
334 initState.addLines(primitive.contents);
335 } else if (name.equals(SpecNaming.CopyState)) {
336 copyState.addLines(primitive.contents);
337 } else if (name.equals(SpecNaming.ClearState)) {
338 clearState.addLines(primitive.contents);
339 } else if (name.equals(SpecNaming.FinalState)) {
340 finalState.addLines(primitive.contents);
341 } else if (name.equals(SpecNaming.PrintState)) {
342 printState.addLines(primitive.contents);
343 } else if (name.equals(SpecNaming.Commutativity)) {
344 processCommutativity(primitive);
349 public String toString() {
350 StringBuilder sb = new StringBuilder("");
351 sb.append(super.toString() + "\n");
352 sb.append("@DeclareState:\n");
353 sb.append(declState);
355 sb.append("@InitState:\n");
356 sb.append(initState);
357 if (!printState.isEmpty()) {
358 sb.append("@Print:\n");
359 sb.append(printState);
362 for (int i = 0; i < commutativityRules.size(); i++) {
363 sb.append("@Commutativity: " + commutativityRules + "\n");
365 return sb.toString();