if (className == null){
//TODO change this to an error message
throw new RuntimeException("variable matching over must be a Class or Type");
}
TagBinding matchBinding = TagBinding.get(className);
if (matchBinding == null) {
//TODO change this to a typecheck error
throw new RuntimeException("Value is not tagged.");
}
//All things we match over must be tagged types
for (Case c : cases) {
if (c.isDefault()) continue;
String tagName = c.getTaggedTypeMatch();
Optional<ClassType> type = env.lookupBinding(tagName, ClassType.class);
NameBinding binding = env.lookup(tagName);
if (binding == null) {
// type wasn't declared...
ToolError.reportError(ErrorMessage.UNKNOWN_TAG, matchingOver);
}
Type t = binding.getType();
if (t instanceof ClassType) {
ClassType classType = (ClassType) t;
String name = classType.getName();
TagBinding tagBinding = TagBinding.get(name);
if (tagBinding == null) {
//not tagged
ToolError.reportError(ErrorMessage.NOT_TAGGED, matchingOver);
}
}
}
// All tagged types must be unique
Set<String> caseSet = new HashSet<String>();
for (Case c : cases) {
if (c.isTyped()) caseSet.add(c.getTaggedTypeMatch());
}
if (caseSet.size() != cases.size()) {
ToolError.reportError(ErrorMessage.DUPLICATE_TAG, matchingOver);
}
// If we've omitted default, we must included all possible sub-tags
if (defaultCase == null) {
//first, the variables tag must use comprised-of!
if (!matchBinding.hasAnyComprises()) {
//TODO change to type-check exception
ToolError.reportError(ErrorMessage.NO_COMPRISES, matchingOver);
}
//next, the match cases must include all those in the comprises-of list
if (!comprisesSatisfied(matchBinding)) {
ToolError.reportError(ErrorMessage.DEFAULT_NOT_PRESENT, matchingOver);
}
}
//A tag cannot be earlier than one of its subtags
for (int i = 0; i < cases.size() - 1; i++) {
Case beforeCase = cases.get(i);
for (int j = i + 1; j < cases.size(); j++) {
Case afterCase = cases.get(j);
if (afterCase.isDefault()) break;
TagBinding afterBinding = TagBinding.get(afterCase.getTaggedTypeMatch());
if (hasMatch(afterBinding, beforeCase.getTaggedTypeMatch())) {
ToolError.reportError(ErrorMessage.SUPERTAG_PRECEEDS_SUBTAG, matchingOver);
}
}