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 finalState;
25 public final Code printState;
26 public final ArrayList<CommutativityRule> commutativityRules;
28 // Whether the state declaration is empty
29 public final boolean emptyState;
30 // Whether we have auto-gen the state initialization code
31 public final boolean autoGenInitial;
32 // Whether we have auto-gen the state copying code
33 public final boolean autoGenCopy;
34 // Whether we have auto-gen the state printing code
35 public final boolean autoGenPrint;
37 public GlobalConstruct(File file, int beginLineNum,
38 ArrayList<String> annotations) throws WrongAnnotationException {
39 super(file, beginLineNum);
40 declState = new ArrayList<VariableDeclaration>();
41 initState = new Code();
42 copyState = new Code();
43 finalState = new Code();
44 printState = new Code();
45 commutativityRules = new ArrayList<CommutativityRule>();
47 processAnnotations(annotations);
49 emptyState = declState.isEmpty();
51 WrongAnnotationException.warning(file, beginLineNum,
52 "The state is empty. Make sure that's what you want!");
55 autoGenInitial = initState.isEmpty();
57 Code code = generateAutoInitalFunction();
58 initState.addLines(code);
61 autoGenCopy = copyState.isEmpty();
63 Code code = generateAutoCopyFunction();
64 copyState.addLines(code);
67 autoGenPrint = printState.isEmpty();
69 Code code = generateAutoPrintFunction();
70 printState.addLines(code);
76 * This function will automatically generate the initial statements for
77 * supported types if the user has not defined the "@Initial" primitive
80 * @return The auto-generated state intialization statements
81 * @throws WrongAnnotationException
83 private Code generateAutoInitalFunction() throws WrongAnnotationException {
84 Code code = new Code();
85 if (emptyState) // Empty state should have empty initial function
87 for (VariableDeclaration decl : declState) {
88 String type = decl.type;
89 String name = decl.name;
91 if (type.equals("int") || type.equals("unsigned")
92 || type.equals("unsigned int")
93 || type.equals("int unsigned") || type.equals("double")
94 || type.equals("double") || type.equals("bool")) {
96 code.addLine(name + " = 0;");
97 } else if (type.equals("IntList") || type.equals("IntSet")
98 || type.equals("IntMap")) {
101 code.addLine(name + " = " + type + "();");
102 } else if (type.equals("IntList *") || type.equals("IntSet *")
103 || type.equals("IntMap *")) {
104 // Supported pointer types
106 String originalType = SpecUtils.trimSpace(type
108 code.addLine(name + " = new " + originalType + "();");
110 WrongAnnotationException
113 "You have types in the state declaration that we do not support auto-gen initial function.");
122 * This function will automatically generate the copy statements for
123 * supported types if the user has not defined the "@Copy" primitive
126 * @return The auto-generated state copy statements
127 * @throws WrongAnnotationException
129 private Code generateAutoCopyFunction() throws WrongAnnotationException {
130 Code code = new Code();
131 if (emptyState) // Empty state should have empty copy function
133 for (VariableDeclaration decl : declState) {
134 String type = decl.type;
135 String name = decl.name;
137 if (type.equals("int") || type.equals("unsigned")
138 || type.equals("unsigned int")
139 || type.equals("int unsigned") || type.equals("double")
140 || type.equals("double") || type.equals("bool")) {
142 code.addLine(SpecNaming.NewStateInst + "->" + name + " = "
143 + SpecNaming.OldStateInst + "->" + name + ";");
144 } else if (type.equals("IntList") || type.equals("IntSet")
145 || type.equals("IntMap")) {
147 // New->q = IntList(OLD->q);
148 code.addLine(SpecNaming.NewStateInst + "->" + name + " = "
149 + type + "(" + SpecNaming.OldStateInst + "->" + name
151 } else if (type.equals("IntList *") || type.equals("IntSet *")
152 || type.equals("IntMap *")) {
153 // Supported pointer types
154 // New->q = new IntList(*OLD->q);
155 String originalType = SpecUtils.trimSpace(type
157 code.addLine(SpecNaming.NewStateInst + "->" + name + " = new "
158 + originalType + "(*" + SpecNaming.OldStateInst + "->"
161 WrongAnnotationException
164 "You have types in the state declaration that we do not support auto-gen copy function.");
173 * This function will automatically generate the printing statements for
174 * supported types if the user has not defined the "@Print" primitive
177 * @return The auto-generated state printing statements
178 * @throws WrongAnnotationException
180 private Code generateAutoPrintFunction() throws WrongAnnotationException {
181 Code code = new Code();
182 if (emptyState) // Empty state should have empty printing function
184 for (VariableDeclaration decl : declState) {
185 String type = decl.type;
186 String name = decl.name;
187 code.addLines(SpecUtils.generatePrintStatement(type, name));
195 * Assert that the global state primitive is valid; if not, throws an
202 * The primitive that we have extracted earlier
203 * @throws WrongAnnotationException
205 private void assertValidPrimitive(File file, Primitive primitive)
206 throws WrongAnnotationException {
207 int lineNum = primitive.beginLineNum;
208 String name = primitive.name;
209 if (!name.equals(SpecNaming.DeclareState)
210 && !name.equals(SpecNaming.InitalState)
211 && !name.equals(SpecNaming.CopyState)
212 && !name.equals(SpecNaming.FinalState)
213 && !name.equals(SpecNaming.Commutativity)
214 && !name.equals(SpecNaming.PrintState)) {
215 WrongAnnotationException.err(file, lineNum, name
216 + " is NOT a valid CDSSpec global state primitive.");
222 * Given a "@DeclareState" primitive that has a list of strings of
223 * declarations, we initialize our local "declState" members.
226 * @throws WrongAnnotationException
228 private void processDeclState(Primitive primitive)
229 throws WrongAnnotationException {
230 for (int i = 0; i < primitive.contents.size(); i++) {
231 int lineNum = i + primitive.beginLineNum;
232 String declLine = primitive.contents.get(i);
233 VariableDeclaration tmp = new VariableDeclaration(file, lineNum,
241 * Given a "@DeclareState" primitive that has a list of strings of
242 * declarations, we initialize our local "declState" members.
245 * @throws WrongAnnotationException
247 private void processCommutativity(Primitive primitive)
248 throws WrongAnnotationException {
249 // Mathch commutativity rule
250 Pattern regexpCommute = Pattern
251 .compile("\\s*(\\w+)\\s*<->\\s*(\\w+)\\s*\\((.*)\\)\\s*$");
252 Matcher matcherCommute = regexpCommute.matcher("");
254 for (int i = 0; i < primitive.contents.size(); i++) {
255 // FIXME: Currently we only allow a one-line commutativity rule
256 int curLineNum = primitive.beginLineNum + i;
257 String line = primitive.contents.get(i);
258 matcherCommute.reset(line);
259 if (matcherCommute.find()) {
260 String method1 = matcherCommute.group(1);
261 String method2 = matcherCommute.group(2);
262 String code = matcherCommute.group(3);
263 String rule = SpecUtils.trimSpace(SpecUtils
264 .trimTrailingCommentSymbol(code));
265 commutativityRules.add(new CommutativityRule(method1, method2,
268 WrongAnnotationException
271 "The @Commutativity annotation should be: @Commutativity: Method1 <-> Method2 (condition)\n\t"
272 + "Problematic line: \"" + line + "\"");
274 // Done with processing the current commutativity
278 private void processAnnotations(ArrayList<String> annotations)
279 throws WrongAnnotationException {
280 IntObj curIdx = new IntObj(0);
281 Primitive primitive = null;
283 while ((primitive = SpecUtils.extractPrimitive(file, beginLineNum,
284 annotations, curIdx)) != null) {
285 String name = primitive.name;
286 assertValidPrimitive(file, primitive);
287 if (primitive.contents.size() == 0)
289 if (name.equals(SpecNaming.DeclareState)) {
290 processDeclState(primitive);
291 } else if (name.equals(SpecNaming.InitalState)) {
292 initState.addLines(primitive.contents);
293 } else if (name.equals(SpecNaming.CopyState)) {
294 copyState.addLines(primitive.contents);
295 } else if (name.equals(SpecNaming.FinalState)) {
296 finalState.addLines(primitive.contents);
297 } else if (name.equals(SpecNaming.PrintState)) {
298 printState.addLines(primitive.contents);
299 } else if (name.equals(SpecNaming.Commutativity)) {
300 processCommutativity(primitive);
305 public String toString() {
306 StringBuilder sb = new StringBuilder("");
307 sb.append(super.toString() + "\n");
308 sb.append("@DeclareState:\n");
309 sb.append(declState);
311 sb.append("@InitState:\n");
312 sb.append(initState);
313 if (!printState.isEmpty()) {
314 sb.append("@Print:\n");
315 sb.append(printState);
318 for (int i = 0; i < commutativityRules.size(); i++) {
319 sb.append("@Commutativity: " + commutativityRules + "\n");
321 return sb.toString();