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