package edu.uci.eecs.specCompiler.codeGenerator;
+import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import edu.uci.eecs.specCompiler.grammerParser.ParseException;
+import edu.uci.eecs.specCompiler.specExtraction.CPClearConstruct;
import edu.uci.eecs.specCompiler.specExtraction.CPDefineCheckConstruct;
+import edu.uci.eecs.specCompiler.specExtraction.CPDefineConstruct;
+import edu.uci.eecs.specCompiler.specExtraction.ClassBeginConstruct;
+import edu.uci.eecs.specCompiler.specExtraction.ClassEndConstruct;
import edu.uci.eecs.specCompiler.specExtraction.ConditionalInterface;
import edu.uci.eecs.specCompiler.specExtraction.Construct;
+import edu.uci.eecs.specCompiler.specExtraction.EntryPointConstruct;
import edu.uci.eecs.specCompiler.specExtraction.GlobalConstruct;
import edu.uci.eecs.specCompiler.specExtraction.InterfaceConstruct;
+import edu.uci.eecs.specCompiler.specExtraction.InterfaceDefineConstruct;
+import edu.uci.eecs.specCompiler.specExtraction.ParserUtils;
import edu.uci.eecs.specCompiler.specExtraction.PotentialCPDefineConstruct;
-import edu.uci.eecs.specCompiler.specExtraction.SpecConstruct;
+import edu.uci.eecs.specCompiler.specExtraction.SourceFileInfo;
+import edu.uci.eecs.specCompiler.specExtraction.SpecExtractor;
+/**
+ * <p>
+ * A specificaiton semantics checker that checks the consistency of the
+ * specifications after they are extracted from the source code.
+ * </p>
+ *
+ * @author peizhaoo
+ *
+ */
public class SemanticsChecker {
- public final ArrayList<SpecConstruct> constructs;
- public final HashMap<String, SpecConstruct> label2Construct;
- public final HashMap<String, SpecConstruct> interfaceName2Construct;
+ public final HashMap<File, SourceFileInfo> srcFilesInfo;
+ public final ArrayList<Construct> constructs;
+ public final HashMap<String, Construct> CPLabel2Construct;
+ public final HashMap<String, PotentialCPDefineConstruct> potentialCPLabel2Construct;
+ public final HashMap<String, InterfaceConstruct> interfaceName2Construct;
+ public final HashMap<String, InterfaceDefineConstruct> interfaceName2DefineConstruct;
+ public final HashMap<String, InterfaceConstruct> CPLabel2InterfaceConstruct;
- public SemanticsChecker(ArrayList<SpecConstruct> constructs) {
- this.constructs = constructs;
- this.label2Construct = new HashMap<String, SpecConstruct>();
- this.interfaceName2Construct = new HashMap<String, SpecConstruct>();
+ public final HashMap<String, Integer> interface2Num;
+ public final HashMap<Integer, String> num2Interface;
+ public final HashMap<String, Integer> hbLabel2Num;
+ public final HashMap<Integer, String> num2HBLabel;
+ public final HashMap<String, Integer> commitPointLabel2Num;
+ public final HashMap<Integer, String> num2CommitPointLabel;
+
+ private HashMap<String, String> options;
+ private HashMap<ConditionalInterface, HashSet<ConditionalInterface>> hbConditions;
+ private ArrayList<EntryPointConstruct> entryPointConstructs;
+ private ClassBeginConstruct classBeginConstruct;
+ private ClassEndConstruct classEndConstruct;
+ private GlobalConstruct globalConstruct;
+
+ private String templateStr;
+ private String templateFullStr;
+ private String className;
+
+ private int _interfaceNum;
+ private int _hbLabelNum;
+ private int _commitPointNum;
+
+ public SemanticsChecker(SpecExtractor extractor) {
+ this.srcFilesInfo = extractor.srcFilesInfo;
+ this.constructs = extractor.getConstructs();
+ this.CPLabel2Construct = new HashMap<String, Construct>();
+ this.potentialCPLabel2Construct = new HashMap<String, PotentialCPDefineConstruct>();
+ this.interfaceName2Construct = new HashMap<String, InterfaceConstruct>();
+ this.interfaceName2DefineConstruct = new HashMap<String, InterfaceDefineConstruct>();
+ this.CPLabel2InterfaceConstruct = new HashMap<String, InterfaceConstruct>();
+ this.entryPointConstructs = new ArrayList<EntryPointConstruct>();
+ this.classBeginConstruct = null;
+ this.classEndConstruct = null;
+
+ this.interface2Num = new HashMap<String, Integer>();
+ this.num2Interface = new HashMap<Integer, String>();
+ this.hbLabel2Num = new HashMap<String, Integer>();
+ this.num2HBLabel = new HashMap<Integer, String>();
+ // Immediately init the true HB-condition to be 0
+ hbLabel2Num.put("", 0);
+ num2HBLabel.put(0, "");
+
+ this.commitPointLabel2Num = new HashMap<String, Integer>();
+ this.num2CommitPointLabel = new HashMap<Integer, String>();
+
+ _interfaceNum = 0;
+ _hbLabelNum = 0;
+ _commitPointNum = 0;
+
+ templateStr = null;
+ templateFullStr = null;
+ className = null;
+ }
+
+ public ClassBeginConstruct getClassBeginConstruct() {
+ return this.classBeginConstruct;
+ }
+
+ public ClassEndConstruct getClassEndConstruct() {
+ return this.classEndConstruct;
+ }
+
+ public String getTemplateFullStr() {
+ return this.templateFullStr;
+ }
+
+ public String getTemplateStr() {
+ return this.templateStr;
+ }
+
+ public String getClassName() {
+ return this.className;
+ }
+
+ public GlobalConstruct getGlobalConstruct() {
+ return this.globalConstruct;
+ }
+
+ public HashMap<ConditionalInterface, HashSet<ConditionalInterface>> getHBConditions() {
+ return this.hbConditions;
}
- private void checkHBLabelConsistency(String interfaceName, String label)
+ /**
+ * Check if the conditional interface is in the HB checking list
+ *
+ * @param condInterface
+ * @return
+ */
+ public boolean containsConditionalInterface(
+ ConditionalInterface condInterface) {
+ if (hbConditions.containsKey(condInterface))
+ return true;
+ for (ConditionalInterface key : hbConditions.keySet()) {
+ if (hbConditions.get(key).contains(condInterface))
+ return true;
+ }
+ return false;
+ }
+
+ public String getOption(String key) {
+ return options.get(key);
+ }
+
+ private void checkHBLabelConsistency(ConditionalInterface inst)
throws SemanticsCheckerException {
+ String interfaceName = inst.interfaceName, label = inst.hbConditionLabel;
if (!interfaceName2Construct.containsKey(interfaceName)) {
throw new SemanticsCheckerException(
- "In global construct, no interface \""
- + interfaceName + "\"!");
- } else {
+ "In global construct, no interface \"" + interfaceName
+ + "\"!");
+ } else if (!label.equals("")) {
InterfaceConstruct iConstruct = (InterfaceConstruct) interfaceName2Construct
- .get(interfaceName).construct;
+ .get(interfaceName);
if (!iConstruct.hbConditions.containsKey(label)) {
throw new SemanticsCheckerException("Interface "
- + interfaceName
- + " doesn't contain HB_codition: " + label
- + "!");
+ + interfaceName + " doesn't contain HB_codition: "
+ + label + "!");
+ }
+
+ // Number the HB-condition label
+ hbLabel2Num.put(label, _hbLabelNum++);
+ num2HBLabel.put(_hbLabelNum, label);
+ }
+ }
+
+ private void checkLabelDuplication(Construct construct, String label)
+ throws SemanticsCheckerException {
+ if (potentialCPLabel2Construct.containsKey(label)
+ || CPLabel2Construct.containsKey(label))
+ throw new SemanticsCheckerException("In construct: " + construct
+ + "\"" + label + "\" has duplication.");
+ }
+
+ private void checkOptions() throws SemanticsCheckerException {
+ // FIXME: We don't have any check here
+ }
+
+ private void postCheck() throws SemanticsCheckerException {
+ // C++ data structure with Class must provide the beginning and ending
+ // of its declaration
+ if (getOption("Class") != null) {
+ if (classBeginConstruct == null || classEndConstruct == null) {
+ throw new SemanticsCheckerException(
+ "Class must provide the boundary explicitly!");
+ }
+ }
+ // It must provide the entry point
+ if (entryPointConstructs.size() == 0) {
+ throw new SemanticsCheckerException(
+ "The program must have at least one entry point!");
+ }
+
+ // Check if interface define construct labels are correct
+ for (String name : interfaceName2DefineConstruct.keySet()) {
+ if (!interfaceName2Construct.containsKey(name)) {
+ throw new SemanticsCheckerException("Label \"" + name
+ + "\" does not have interface declaration!");
}
}
}
boolean hasGlobalConstruct = false;
// First grab the information from the interface
for (int i = 0; i < constructs.size(); i++) {
- Construct inst = constructs.get(i).construct;
+ Construct inst = constructs.get(i);
if (inst instanceof InterfaceConstruct) {
InterfaceConstruct iConstruct = (InterfaceConstruct) inst;
- interfaceName2Construct.put(iConstruct.name, constructs.get(i));
+ if (interfaceName2Construct.containsKey(iConstruct.name)) {
+ throw new SemanticsCheckerException("Interface name: "
+ + iConstruct.name + " duplicates!");
+ }
+ // Number the interface label
+ interface2Num.put(iConstruct.name, _interfaceNum++);
+ num2Interface.put(_interfaceNum, iConstruct.name);
+
+ interfaceName2Construct.put(iConstruct.name,
+ (InterfaceConstruct) constructs.get(i));
+
+ for (int j = 0; j < iConstruct.commitPointSet.size(); j++) {
+ String label = iConstruct.commitPointSet.get(j);
+ // if (!CPLabel2InterfaceConstruct.containsKey(label)) {
+ // CPLabel2InterfaceConstruct.put(label,
+ // new ArrayList<InterfaceConstruct>());
+ // }
+ // CPLabel2InterfaceConstruct.get(label).add(iConstruct);
+ if (!CPLabel2InterfaceConstruct.containsKey(label)) {
+ CPLabel2InterfaceConstruct.put(label, iConstruct);
+ } else {
+ throw new SemanticsCheckerException(
+ "Commit point has multiple interfaces!");
+ }
+
+ }
}
}
+ String label;
for (int i = 0; i < constructs.size(); i++) {
- SpecConstruct inst = constructs.get(i);
- Construct construct = inst.construct;
+ Construct construct = constructs.get(i);
if (construct instanceof GlobalConstruct) {
GlobalConstruct theConstruct = (GlobalConstruct) construct;
+ globalConstruct = theConstruct;
if (!hasGlobalConstruct)
hasGlobalConstruct = true;
else {
throw new SemanticsCheckerException(
"More than one global construct!");
}
+ // Record the options and check them
+ options = theConstruct.options;
- HashMap<ConditionalInterface, HashSet<ConditionalInterface>> hbConditions = theConstruct.hbRelations;
+ // Record the HB conditions and check it
+ hbConditions = theConstruct.hbRelations;
for (ConditionalInterface left : hbConditions.keySet()) {
HashSet<ConditionalInterface> set = hbConditions.get(left);
- checkHBLabelConsistency(left.interfaceName, left.hbConditionLabel);
+ checkHBLabelConsistency(left);
+
for (ConditionalInterface right : set) {
- checkHBLabelConsistency(right.interfaceName, right.hbConditionLabel);
+ checkHBLabelConsistency(right);
}
}
} else if (construct instanceof PotentialCPDefineConstruct) {
PotentialCPDefineConstruct theConstruct = (PotentialCPDefineConstruct) construct;
- label2Construct.put(theConstruct.label, inst);
+ label = theConstruct.label;
+ checkLabelDuplication(construct, label);
+ // Number the commit point potential commit point label
+ commitPointLabel2Num.put(label, _commitPointNum++);
+ num2CommitPointLabel.put(_commitPointNum, label);
+
+ potentialCPLabel2Construct.put(label,
+ (PotentialCPDefineConstruct) construct);
} else if (construct instanceof CPDefineCheckConstruct) {
CPDefineCheckConstruct theConstruct = (CPDefineCheckConstruct) construct;
- label2Construct.put(theConstruct.label, inst);
+ label = theConstruct.label;
+ checkLabelDuplication(construct, label);
+ // Number the commit point define check label
+ commitPointLabel2Num.put(label, _commitPointNum++);
+ num2CommitPointLabel.put(_commitPointNum, label);
+
+ CPLabel2Construct.put(label, construct);
+ } else if (construct instanceof CPClearConstruct) {
+ CPClearConstruct theConstruct = (CPClearConstruct) construct;
+ label = theConstruct.label;
+ checkLabelDuplication(construct, label);
+ // Number the commit point define check label
+ commitPointLabel2Num.put(label, _commitPointNum++);
+ num2CommitPointLabel.put(_commitPointNum, label);
+
+ CPLabel2Construct.put(label, construct);
+ } else if (construct instanceof CPDefineConstruct) {
+ CPDefineConstruct theConstruct = (CPDefineConstruct) construct;
+ label = theConstruct.label;
+ checkLabelDuplication(construct, label);
+ // Number the commit point define label
+ commitPointLabel2Num.put(label, _commitPointNum++);
+ num2CommitPointLabel.put(_commitPointNum, label);
+
+ CPLabel2Construct.put(label, construct);
+ } else if (construct instanceof EntryPointConstruct) {
+ entryPointConstructs.add((EntryPointConstruct) construct);
+ } else if (construct instanceof InterfaceDefineConstruct) {
+ InterfaceDefineConstruct theConstruct = (InterfaceDefineConstruct) construct;
+ String name = theConstruct.name;
+ if (interfaceName2DefineConstruct.containsKey(name)) {
+ throw new SemanticsCheckerException(
+ "Interface define label duplicates!");
+ }
+ interfaceName2DefineConstruct.put(name, theConstruct);
+ } else if (construct instanceof ClassBeginConstruct) {
+ classBeginConstruct = (ClassBeginConstruct) construct;
+ ArrayList<String> content = srcFilesInfo
+ .get(classBeginConstruct.file).content;
+ String firstLine = content
+ .get(classBeginConstruct.beginLineNum + 1), secondLine;
+ if (firstLine.startsWith("template")) {
+ secondLine = content
+ .get(classBeginConstruct.beginLineNum + 1);
+ templateFullStr = firstLine;
+ templateStr = ParserUtils.getTemplateStr(firstLine);
+ className = ParserUtils.getClassName(secondLine);
+ } else {
+ className = ParserUtils.getClassName(firstLine);
+ }
+
+ } else if (construct instanceof ClassEndConstruct) {
+ classEndConstruct = (ClassEndConstruct) construct;
+ className = getOption("CLASS");
}
}
}
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("Interface name 2 Construct:\n");
+ for (String interfaceName : interfaceName2Construct.keySet()) {
+ sb.append(interfaceName + "\t"
+ + interfaceName2Construct.get(interfaceName) + "\n");
+ }
+
+ sb.append("Interface name 2 define construct:\n");
+ for (String interfaceName : interfaceName2DefineConstruct.keySet()) {
+ sb.append(interfaceName + "\t"
+ + interfaceName2DefineConstruct.get(interfaceName) + "\n");
+ }
+
+ sb.append("Potential commit point label 2 Construct:\n");
+ for (String label : potentialCPLabel2Construct.keySet()) {
+ sb.append(label + "\t" + potentialCPLabel2Construct.get(label)
+ + "\n");
+ }
+
+ sb.append("Commit point label 2 Construct:\n");
+ for (String label : CPLabel2Construct.keySet()) {
+ sb.append(label + "\t" + CPLabel2Construct.get(label) + "\n");
+ }
+ return sb.toString();
+ }
}