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