add Commit point clear construct
[cdsspec-compiler.git] / src / edu / uci / eecs / specCompiler / codeGenerator / SemanticsChecker.java
1 package edu.uci.eecs.specCompiler.codeGenerator;
2
3 import java.io.File;
4 import java.util.ArrayList;
5 import java.util.HashMap;
6 import java.util.HashSet;
7
8 import edu.uci.eecs.specCompiler.grammerParser.ParseException;
9 import edu.uci.eecs.specCompiler.specExtraction.CPDefineCheckConstruct;
10 import edu.uci.eecs.specCompiler.specExtraction.CPDefineConstruct;
11 import edu.uci.eecs.specCompiler.specExtraction.ClassBeginConstruct;
12 import edu.uci.eecs.specCompiler.specExtraction.ClassEndConstruct;
13 import edu.uci.eecs.specCompiler.specExtraction.ConditionalInterface;
14 import edu.uci.eecs.specCompiler.specExtraction.Construct;
15 import edu.uci.eecs.specCompiler.specExtraction.EntryPointConstruct;
16 import edu.uci.eecs.specCompiler.specExtraction.GlobalConstruct;
17 import edu.uci.eecs.specCompiler.specExtraction.InterfaceConstruct;
18 import edu.uci.eecs.specCompiler.specExtraction.InterfaceDefineConstruct;
19 import edu.uci.eecs.specCompiler.specExtraction.ParserUtils;
20 import edu.uci.eecs.specCompiler.specExtraction.PotentialCPDefineConstruct;
21 import edu.uci.eecs.specCompiler.specExtraction.SourceFileInfo;
22 import edu.uci.eecs.specCompiler.specExtraction.SpecExtractor;
23
24 public class SemanticsChecker {
25         public final HashMap<File, SourceFileInfo> srcFilesInfo;
26         public final ArrayList<Construct> constructs;
27         public final HashMap<String, Construct> CPLabel2Construct;
28         public final HashMap<String, PotentialCPDefineConstruct> potentialCPLabel2Construct;
29         public final HashMap<String, InterfaceConstruct> interfaceName2Construct;
30         public final HashMap<String, InterfaceDefineConstruct> interfaceName2DefineConstruct;
31         public final HashMap<String, InterfaceConstruct> CPLabel2InterfaceConstruct;
32
33         public final HashMap<String, Integer> interface2Num;
34         public final HashMap<Integer, String> num2Interface;
35         public final HashMap<String, Integer> hbLabel2Num;
36         public final HashMap<Integer, String> num2HBLabel;
37         public final HashMap<String, Integer> commitPointLabel2Num;
38         public final HashMap<Integer, String> num2CommitPointLabel;
39
40         private HashMap<String, String> options;
41         private HashMap<ConditionalInterface, HashSet<ConditionalInterface>> hbConditions;
42         private ArrayList<EntryPointConstruct> entryPointConstructs;
43         private ClassBeginConstruct classBeginConstruct;
44         private ClassEndConstruct classEndConstruct;
45         private GlobalConstruct globalConstruct;
46
47         private String templateStr;
48         private String templateFullStr;
49         private String className;
50
51         private int _interfaceNum;
52         private int _hbLabelNum;
53         private int _commitPointNum;
54
55         public SemanticsChecker(SpecExtractor extractor) {
56                 this.srcFilesInfo = extractor.srcFilesInfo;
57                 this.constructs = extractor.getConstructs();
58                 this.CPLabel2Construct = new HashMap<String, Construct>();
59                 this.potentialCPLabel2Construct = new HashMap<String, PotentialCPDefineConstruct>();
60                 this.interfaceName2Construct = new HashMap<String, InterfaceConstruct>();
61                 this.interfaceName2DefineConstruct = new HashMap<String, InterfaceDefineConstruct>();
62                 this.CPLabel2InterfaceConstruct = new HashMap<String, InterfaceConstruct>();
63                 this.entryPointConstructs = new ArrayList<EntryPointConstruct>();
64                 this.classBeginConstruct = null;
65                 this.classEndConstruct = null;
66
67                 this.interface2Num = new HashMap<String, Integer>();
68                 this.num2Interface = new HashMap<Integer, String>();
69                 this.hbLabel2Num = new HashMap<String, Integer>();
70                 this.num2HBLabel = new HashMap<Integer, String>();
71                 // Immediately init the true HB-condition to be 0
72                 hbLabel2Num.put("", 0);
73                 num2HBLabel.put(0, "");
74
75                 this.commitPointLabel2Num = new HashMap<String, Integer>();
76                 this.num2CommitPointLabel = new HashMap<Integer, String>();
77
78                 _interfaceNum = 0;
79                 _hbLabelNum = 0;
80                 _commitPointNum = 0;
81
82                 templateStr = null;
83                 templateFullStr = null;
84                 className = null;
85         }
86
87         public ClassBeginConstruct getClassBeginConstruct() {
88                 return this.classBeginConstruct;
89         }
90
91         public ClassEndConstruct getClassEndConstruct() {
92                 return this.classEndConstruct;
93         }
94
95         public String getTemplateFullStr() {
96                 return this.templateFullStr;
97         }
98
99         public String getTemplateStr() {
100                 return this.templateStr;
101         }
102
103         public String getClassName() {
104                 return this.className;
105         }
106
107         public GlobalConstruct getGlobalConstruct() {
108                 return this.globalConstruct;
109         }
110
111         public HashMap<ConditionalInterface, HashSet<ConditionalInterface>> getHBConditions() {
112                 return this.hbConditions;
113         }
114
115         /**
116          * Check if the conditional interface is in the HB checking list
117          * 
118          * @param condInterface
119          * @return
120          */
121         public boolean containsConditionalInterface(
122                         ConditionalInterface condInterface) {
123                 if (hbConditions.containsKey(condInterface))
124                         return true;
125                 for (ConditionalInterface key : hbConditions.keySet()) {
126                         if (hbConditions.get(key).contains(condInterface))
127                                 return true;
128                 }
129                 return false;
130         }
131
132         public String getOption(String key) {
133                 return options.get(key);
134         }
135
136         private void checkHBLabelConsistency(ConditionalInterface inst)
137                         throws SemanticsCheckerException {
138                 String interfaceName = inst.interfaceName, label = inst.hbConditionLabel;
139                 if (!interfaceName2Construct.containsKey(interfaceName)) {
140                         throw new SemanticsCheckerException(
141                                         "In global construct, no interface \"" + interfaceName
142                                                         + "\"!");
143                 } else if (!label.equals("")) {
144                         InterfaceConstruct iConstruct = (InterfaceConstruct) interfaceName2Construct
145                                         .get(interfaceName);
146                         if (!iConstruct.hbConditions.containsKey(label)) {
147                                 throw new SemanticsCheckerException("Interface "
148                                                 + interfaceName + " doesn't contain HB_codition: "
149                                                 + label + "!");
150                         }
151
152                         // Number the HB-condition label
153                         hbLabel2Num.put(label, _hbLabelNum++);
154                         num2HBLabel.put(_hbLabelNum, label);
155                 }
156         }
157
158         private void checkLabelDuplication(Construct construct, String label)
159                         throws SemanticsCheckerException {
160                 if (potentialCPLabel2Construct.containsKey(label)
161                                 || CPLabel2Construct.containsKey(label))
162                         throw new SemanticsCheckerException("In construct: " + construct
163                                         + "\"" + label + "\" has duplication.");
164         }
165
166         private void checkOptions() throws SemanticsCheckerException {
167                 // FIXME: We don't have any check here
168         }
169
170         private void postCheck() throws SemanticsCheckerException {
171                 // C++ data structure with Class must provide the beginning and ending
172                 // of its declaration
173                 if (getOption("Class") != null) {
174                         if (classBeginConstruct == null || classEndConstruct == null) {
175                                 throw new SemanticsCheckerException(
176                                                 "Class must provide the boundary explicitly!");
177                         }
178                 }
179                 // It must provide the entry point
180                 if (entryPointConstructs.size() == 0) {
181                         throw new SemanticsCheckerException(
182                                         "The program must have at least one entry point!");
183                 }
184
185                 // Check if interface define construct labels are correct
186                 for (String name : interfaceName2DefineConstruct.keySet()) {
187                         if (!interfaceName2Construct.containsKey(name)) {
188                                 throw new SemanticsCheckerException("Label \"" + name
189                                                 + "\" does not have interface declaration!");
190                         }
191                 }
192         }
193
194         public void check() throws SemanticsCheckerException {
195                 boolean hasGlobalConstruct = false;
196                 // First grab the information from the interface
197                 for (int i = 0; i < constructs.size(); i++) {
198                         Construct inst = constructs.get(i);
199                         if (inst instanceof InterfaceConstruct) {
200                                 InterfaceConstruct iConstruct = (InterfaceConstruct) inst;
201                                 if (interfaceName2Construct.containsKey(iConstruct.name)) {
202                                         throw new SemanticsCheckerException("Interface name: "
203                                                         + iConstruct.name + " duplicates!");
204                                 }
205                                 // Number the interface label
206                                 interface2Num.put(iConstruct.name, _interfaceNum++);
207                                 num2Interface.put(_interfaceNum, iConstruct.name);
208
209                                 interfaceName2Construct.put(iConstruct.name,
210                                                 (InterfaceConstruct) constructs.get(i));
211
212                                 for (int j = 0; j < iConstruct.commitPointSet.size(); j++) {
213                                         String label = iConstruct.commitPointSet.get(j);
214 //                                      if (!CPLabel2InterfaceConstruct.containsKey(label)) {
215 //                                              CPLabel2InterfaceConstruct.put(label,
216 //                                                              new ArrayList<InterfaceConstruct>());
217 //                                      }
218 //                                      CPLabel2InterfaceConstruct.get(label).add(iConstruct);
219                                         if (!CPLabel2InterfaceConstruct.containsKey(label)) {
220                                                 CPLabel2InterfaceConstruct.put(label, iConstruct);
221                                         } else {
222                                                 throw new SemanticsCheckerException(
223                                                                 "Commit point has multiple interfaces!");
224                                         }
225                                         
226                                 }
227                         }
228                 }
229
230                 String label;
231                 for (int i = 0; i < constructs.size(); i++) {
232                         Construct construct = constructs.get(i);
233                         if (construct instanceof GlobalConstruct) {
234                                 GlobalConstruct theConstruct = (GlobalConstruct) construct;
235                                 globalConstruct = theConstruct;
236                                 if (!hasGlobalConstruct)
237                                         hasGlobalConstruct = true;
238                                 else {
239                                         throw new SemanticsCheckerException(
240                                                         "More than one global construct!");
241                                 }
242                                 // Record the options and check them
243                                 options = theConstruct.options;
244
245                                 // Record the HB conditions and check it
246                                 hbConditions = theConstruct.hbRelations;
247                                 for (ConditionalInterface left : hbConditions.keySet()) {
248                                         HashSet<ConditionalInterface> set = hbConditions.get(left);
249                                         checkHBLabelConsistency(left);
250
251                                         for (ConditionalInterface right : set) {
252                                                 checkHBLabelConsistency(right);
253                                         }
254                                 }
255                         } else if (construct instanceof PotentialCPDefineConstruct) {
256                                 PotentialCPDefineConstruct theConstruct = (PotentialCPDefineConstruct) construct;
257                                 label = theConstruct.label;
258                                 checkLabelDuplication(construct, label);
259                                 // Number the commit point potential commit point label
260                                 commitPointLabel2Num.put(label, _commitPointNum++);
261                                 num2CommitPointLabel.put(_commitPointNum, label);
262
263                                 potentialCPLabel2Construct.put(label,
264                                                 (PotentialCPDefineConstruct) construct);
265                         } else if (construct instanceof CPDefineCheckConstruct) {
266                                 CPDefineCheckConstruct theConstruct = (CPDefineCheckConstruct) construct;
267                                 label = theConstruct.label;
268                                 checkLabelDuplication(construct, label);
269                                 // Number the commit point define check label
270                                 commitPointLabel2Num.put(label, _commitPointNum++);
271                                 num2CommitPointLabel.put(_commitPointNum, label);
272
273                                 CPLabel2Construct.put(label, construct);
274                         } else if (construct instanceof CPDefineConstruct) {
275                                 CPDefineConstruct theConstruct = (CPDefineConstruct) construct;
276                                 label = theConstruct.label;
277                                 checkLabelDuplication(construct, label);
278                                 // Number the commit point define label
279                                 commitPointLabel2Num.put(label, _commitPointNum++);
280                                 num2CommitPointLabel.put(_commitPointNum, label);
281
282                                 CPLabel2Construct.put(label, construct);
283                         } else if (construct instanceof EntryPointConstruct) {
284                                 entryPointConstructs.add((EntryPointConstruct) construct);
285                         } else if (construct instanceof InterfaceDefineConstruct) {
286                                 InterfaceDefineConstruct theConstruct = (InterfaceDefineConstruct) construct;
287                                 String name = theConstruct.name;
288                                 if (interfaceName2DefineConstruct.containsKey(name)) {
289                                         throw new SemanticsCheckerException(
290                                                         "Interface define label duplicates!");
291                                 }
292                                 interfaceName2DefineConstruct.put(name, theConstruct);
293                         } else if (construct instanceof ClassBeginConstruct) {
294                                 classBeginConstruct = (ClassBeginConstruct) construct;
295                                 ArrayList<String> content = srcFilesInfo
296                                                 .get(classBeginConstruct.file).content;
297                                 String firstLine = content
298                                                 .get(classBeginConstruct.beginLineNum + 1), secondLine;
299                                 if (firstLine.startsWith("template")) {
300                                         secondLine = content
301                                                         .get(classBeginConstruct.beginLineNum + 1);
302                                         templateFullStr = firstLine;
303                                         templateStr = ParserUtils.getTemplateStr(firstLine);
304                                         className = ParserUtils.getClassName(secondLine);
305                                 } else {
306                                         className = ParserUtils.getClassName(firstLine);
307                                 }
308
309                         } else if (construct instanceof ClassEndConstruct) {
310                                 classEndConstruct = (ClassEndConstruct) construct;
311                                 className = getOption("CLASS");
312                         }
313                 }
314         }
315
316         public String toString() {
317                 StringBuilder sb = new StringBuilder();
318
319                 sb.append("Interface name 2 Construct:\n");
320                 for (String interfaceName : interfaceName2Construct.keySet()) {
321                         sb.append(interfaceName + "\t"
322                                         + interfaceName2Construct.get(interfaceName) + "\n");
323                 }
324
325                 sb.append("Interface name 2 define construct:\n");
326                 for (String interfaceName : interfaceName2DefineConstruct.keySet()) {
327                         sb.append(interfaceName + "\t"
328                                         + interfaceName2DefineConstruct.get(interfaceName) + "\n");
329                 }
330
331                 sb.append("Potential commit point label 2 Construct:\n");
332                 for (String label : potentialCPLabel2Construct.keySet()) {
333                         sb.append(label + "\t" + potentialCPLabel2Construct.get(label)
334                                         + "\n");
335                 }
336
337                 sb.append("Commit point label 2 Construct:\n");
338                 for (String label : CPLabel2Construct.keySet()) {
339                         sb.append(label + "\t" + CPLabel2Construct.get(label) + "\n");
340                 }
341                 return sb.toString();
342         }
343 }