souffle
2.0.2-371-g6315b36
|
Definition at line 108 of file SemanticChecker.cpp.
◆ SemanticCheckerImpl()
souffle::ast::transform::SemanticCheckerImpl::SemanticCheckerImpl |
( |
TranslationUnit & |
tu | ) |
|
Definition at line 149 of file SemanticChecker.cpp.
157 for (
auto& relname : suppressedRelations) {
158 const std::vector<std::string> comps =
splitString(relname,
'.');
159 if (!comps.empty()) {
161 QualifiedName relid(comps[0]);
162 for (
size_t i = 1;
i < comps.size();
i++) {
163 relid.append(comps[
i]);
188 std::map<SrcLocation, std::set<const Clause*>> multiRuleMap;
191 multiRuleMap[clause->getSrcLoc()].insert(clause);
195 for (
const auto& multiRule : multiRuleMap) {
205 GroundedTermsChecker().verify(
tu);
208 TypeChecker().verify(
tu);
217 const Literal* foundLiteral =
nullptr;
222 std::set<const Relation*, NameComparison> sortedRelSet(relSet.begin(), relSet.end());
224 std::string relationsListStr =
toString(
join(sortedRelSet,
",",
225 [](std::ostream& out,
const Relation* r) { out << r->getQualifiedName(); }));
226 std::vector<DiagnosticMessage> messages;
227 messages.push_back(DiagnosticMessage(
228 "Relation " +
toString(cur->getQualifiedName()), cur->getSrcLoc()));
229 std::string negOrAgg = hasNegation ?
"negation" :
"aggregation";
231 DiagnosticMessage(
"has cyclic " + negOrAgg, foundLiteral->getSrcLoc()));
233 DiagnosticMessage(
"Unable to stratify relation(s) {" + relationsListStr +
"}"),
References souffle::ast::Program::getRelations(), program, rel(), and souffle::SUPPRESSED.
◆ checkAggregator()
void souffle::ast::transform::SemanticCheckerImpl::checkAggregator |
( |
const Aggregator & |
aggregator | ) |
|
|
private |
Definition at line 375 of file SemanticChecker.cpp.
376 if (candidateAggregate != aggregator) {
388 Clause dummyClauseOther;
391 if (
isDependent(dummyClauseAggregator, dummyClauseOther) &&
392 isDependent(dummyClauseOther, dummyClauseAggregator)) {
393 report.
addError(
"Mutually dependent aggregate", aggregator.getSrcLoc());
398 for (Literal* literal : aggregator.getBodyLiterals()) {
404 if (
const auto* agg =
dynamic_cast<const Aggregator*
>(&arg)) {
406 }
else if (
const auto* func =
dynamic_cast<const Functor*
>(&arg)) {
407 for (
auto arg : func->getArguments()) {
References souffle::clone().
◆ checkArgument()
void souffle::ast::transform::SemanticCheckerImpl::checkArgument |
( |
const Argument & |
arg | ) |
|
|
private |
◆ checkAtom()
void souffle::ast::transform::SemanticCheckerImpl::checkAtom |
( |
const Atom & |
atom | ) |
|
|
private |
Definition at line 248 of file SemanticChecker.cpp.
252 "Mismatching arity of relation " +
toString(atom.getQualifiedName()), atom.getSrcLoc());
255 for (
const Argument* arg : atom.getArguments()) {
262 auto* type = sumTypesBranches.getType(adt.getConstructor());
263 if (type == nullptr) {
264 report.addError(
"Undeclared branch", adt.getSrcLoc());
◆ checkBranchInits()
void souffle::ast::transform::SemanticCheckerImpl::checkBranchInits |
( |
| ) |
|
|
private |
◆ checkClause()
void souffle::ast::transform::SemanticCheckerImpl::checkClause |
( |
const Clause & |
clause | ) |
|
|
private |
Definition at line 470 of file SemanticChecker.cpp.
474 : clause.getBodyLiterals()) {
486 std::map<std::string, int> var_count;
487 std::map<std::string, const ast::Variable*> var_pos;
489 var_count[var.getName()]++;
490 var_pos[var.getName()] = &var;
492 for (
const auto& cur : var_count) {
493 int numAppearances = cur.second;
494 const auto& varName = cur.first;
495 const auto& varLocation = var_pos[varName]->getSrcLoc();
496 if (varName[0] ==
'_') {
497 assert(varName.size() > 1 &&
"named variable should not be a single underscore");
498 if (numAppearances > 1) {
499 report.
addWarning(
"Variable " + varName +
" marked as singleton but occurs more than once",
506 if (clause.getExecutionPlan() !=
nullptr) {
507 auto numAtoms = getBodyLiterals<Atom>(clause).size();
508 for (
const auto& cur : clause.getExecutionPlan()->getOrders()) {
509 bool isComplete =
true;
510 auto order = cur.second->getOrder();
511 for (
unsigned i = 1;
i <= order.size();
i++) {
517 if (order.size() != numAtoms || !isComplete) {
518 report.
addError(
"Invalid execution order in plan", cur.second->getSrcLoc());
526 report.
addError(
"Auto-increment functor in a recursive rule", ctr.getSrcLoc());
532 std::map<std::string, int> var_count;
533 std::map<std::string, const ast::Variable*> var_pos;
◆ checkComplexRule()
void souffle::ast::transform::SemanticCheckerImpl::checkComplexRule |
( |
std::set< const Clause * > |
multiRule | ) |
|
|
private |
Definition at line 537 of file SemanticChecker.cpp.
541 var_count[var.getName()]++;
542 var_pos[var.getName()] = &var;
547 for (
auto clause : multiRule) {
549 var_count[var.getName()]++;
550 var_pos[var.getName()] = &var;
555 for (
const auto& cur : var_count) {
556 int numAppearances = cur.second;
557 const auto& varName = cur.first;
558 const auto& varLocation = var_pos[varName]->getSrcLoc();
559 if (varName[0] !=
'_' && numAppearances == 1) {
560 report.
addWarning(
"Variable " + varName +
" only occurs once", varLocation);
566 const auto& attributes =
relation.getAttributes();
567 assert(attributes.size() ==
relation.getArity() &&
"mismatching attribute size and arity");
References souffle::ast::visitDepthFirst().
◆ checkConstant()
void souffle::ast::transform::SemanticCheckerImpl::checkConstant |
( |
const Argument & |
argument | ) |
|
|
private |
◆ checkFact()
void souffle::ast::transform::SemanticCheckerImpl::checkFact |
( |
const Clause & |
fact | ) |
|
|
private |
Definition at line 449 of file SemanticChecker.cpp.
457 for (
auto* arg : head->getArguments()) {
458 if (!isConstantArgument(arg)) {
459 report.
addError(
"Argument in fact is not constant", arg->getSrcLoc());
◆ checkInlining()
void souffle::ast::transform::SemanticCheckerImpl::checkInlining |
( |
| ) |
|
|
private |
Definition at line 791 of file SemanticChecker.cpp.
795 "IO relation " +
toString(
relation->getQualifiedName()) +
" cannot be inlined",
811 for (
const Relation*
rel : inlinedRelations) {
812 unvisited.insert(
rel);
816 std::map<const Relation*, const Relation*> origins;
818 std::vector<QualifiedName> result =
822 if (!result.empty()) {
826 std::stringstream cycle;
827 cycle <<
"{" << cycleOrigin->getQualifiedName();
830 for (
int i = result.size() - 2;
i >= 0;
i--) {
831 cycle <<
", " << result[
i];
837 "Cannot inline cyclically dependent relations " + cycle.str(), cycleOrigin->getSrcLoc());
846 if (associatedRelation !=
nullptr && isInline(associatedRelation)) {
848 if (isA<Counter>(&arg)) {
850 "Cannot inline literal containing a counter argument '$'", arg.getSrcLoc());
857 for (
const Relation*
rel : inlinedRelations) {
860 if (isA<Counter>(&arg)) {
862 "Cannot inline clause containing a counter argument '$'", arg.getSrcLoc());
875 for (
const Relation*
rel : inlinedRelations) {
876 bool foundNonNegatable =
false;
879 std::set<std::string> headVariables;
881 [&](
const ast::Variable& var) { headVariables.insert(var.getName()); });
884 std::set<std::string> bodyVariables;
886 [&](
const ast::Variable& var) { bodyVariables.insert(var.getName()); });
890 for (
const std::string& var : bodyVariables) {
891 if (headVariables.find(var) == headVariables.end()) {
892 nonNegatableRelations.insert(
rel);
893 foundNonNegatable =
true;
898 if (foundNonNegatable) {
906 Relation* associatedRelation =
getRelation(
program, neg.getAtom()->getQualifiedName());
907 if (associatedRelation !=
nullptr &&
908 nonNegatableRelations.find(associatedRelation) != nonNegatableRelations.end()) {
910 "Cannot inline negated relation which may introduce new variables", neg.getSrcLoc());
929 if (
rel !=
nullptr && isInline(
rel)) {
930 report.
addError(
"Cannot inline relations that appear in aggregator", subatom.getSrcLoc());
951 std::function<std::pair<bool, SrcLocation>(
const Node*)> checkInvalidUnderscore = [&](
const Node* node) {
952 if (isA<UnnamedVariable>(node)) {
954 return std::make_pair(
true, node->getSrcLoc());
955 }
else if (isA<Aggregator>(node)) {
957 return std::make_pair(
false, node->getSrcLoc());
961 for (
const Node* child : node->getChildNodes()) {
962 std::pair<bool, SrcLocation> childStatus = checkInvalidUnderscore(child);
963 if (childStatus.first) {
969 return std::make_pair(
false, node->getSrcLoc());
974 const Atom* associatedAtom = negation.getAtom();
975 const Relation* associatedRelation =
getRelation(
program, associatedAtom->getQualifiedName());
976 if (associatedRelation !=
nullptr && isInline(associatedRelation)) {
977 std::pair<bool, SrcLocation> atomStatus = checkInvalidUnderscore(associatedAtom);
978 if (atomStatus.first) {
980 "Cannot inline negated atom containing an unnamed variable unless the variable is "
981 "within an aggregator",
990 std::map<std::string, SrcLocation> names;
References souffle::ErrorReport::addError(), relation, and souffle::toString().
◆ checkIO()
void souffle::ast::transform::SemanticCheckerImpl::checkIO |
( |
| ) |
|
|
private |
◆ checkLiteral()
void souffle::ast::transform::SemanticCheckerImpl::checkLiteral |
( |
const Literal & |
literal | ) |
|
|
private |
Definition at line 309 of file SemanticChecker.cpp.
313 if (
const auto* constraint = as<BinaryConstraint>(literal)) {
317 std::set<const UnnamedVariable*> unnamedInRecord;
319 for (
auto* arg : record.getArguments()) {
320 if (auto* unnamed = as<UnnamedVariable>(arg)) {
321 unnamedInRecord.insert(unnamed);
327 if (isA<Aggregator>(*constraint->getLHS()) || isA<Aggregator>(*constraint->getRHS())) {
331 for (
auto* unnamed : getUnnamedVariables(*constraint)) {
332 if (!
contains(unnamedInRecord, unnamed)) {
333 report.
addError(
"Underscore in binary relation", unnamed->getSrcLoc());
◆ checkNamespaces()
void souffle::ast::transform::SemanticCheckerImpl::checkNamespaces |
( |
| ) |
|
|
private |
◆ checkRelation()
void souffle::ast::transform::SemanticCheckerImpl::checkRelation |
( |
const Relation & |
relation | ) |
|
|
private |
◆ checkRelationDeclaration()
void souffle::ast::transform::SemanticCheckerImpl::checkRelationDeclaration |
( |
const Relation & |
relation | ) |
|
|
private |
Definition at line 571 of file SemanticChecker.cpp.
573 {
return type->getQualifiedName() == typeName; });
581 for (
size_t j = 0;
j <
i;
j++) {
582 if (attr->getName() == attributes[
j]->getName()) {
592 const auto& attributes =
relation.getAttributes();
593 assert(attributes.size() == 2 &&
"mismatching attribute size and arity");
◆ checkWitnessProblem()
void souffle::ast::transform::SemanticCheckerImpl::checkWitnessProblem |
( |
| ) |
|
|
private |
◆ isDependent()
bool souffle::ast::transform::SemanticCheckerImpl::isDependent |
( |
const Clause & |
agg1, |
|
|
const Clause & |
agg2 |
|
) |
| |
|
private |
agg1, agg2 are clauses which contain no head, and consist of a single literal that contains an aggregate.
agg1 is dependent on agg2 if agg1 contains a variable which is grounded by agg2, and not by agg1.
Definition at line 350 of file SemanticChecker.cpp.
354 if (var == searchVar) {
355 matchingVarPtr = &var;
360 if (matchingVarPtr !=
nullptr) {
361 if (!groundedInAgg1[&searchVar] && groundedInAgg2[matchingVarPtr]) {
372 Clause dummyClauseAggregator;
◆ ioTypes
◆ precedenceGraph
◆ program
const Program& souffle::ast::transform::SemanticCheckerImpl::program = tu.getProgram() |
|
private |
◆ recursiveClauses
◆ report
ErrorReport& souffle::ast::transform::SemanticCheckerImpl::report = tu.getErrorReport() |
|
private |
◆ sccGraph
◆ sumTypesBranches
◆ tu
◆ typeEnv
The documentation for this struct was generated from the following file:
bool contains(const C &container, const typename C::value_type &element)
A utility to check generically whether a given element is contained in a given container.
bool isIO(const Relation *relation) const
size_t getSCC(const Relation *rel) const
Get the SCC of the given relation.
bool isFact(const Clause &clause)
Returns whether the given clause is a fact.
std::vector< Clause * > getClauses() const
Return clauses.
bool hasClauseWithNegatedRelation(const Relation *relation, const Relation *negRelation, const Program *program, const Literal *&foundLiteral)
Returns whether the given relation has any clauses which contain a negation of a specific relation.
const std::string & toString(const std::string &str)
A generic function converting strings into strings (trivial case).
bool hasClauseWithAggregatedRelation(const Relation *relation, const Relation *aggRelation, const Program *program, const Literal *&foundLiteral)
Returns whether the given relation has any clauses which contain an aggregation over of a specific re...
auto clone(const std::vector< A * > &xs)
ErrorReport & getErrorReport()
Return error report.
bool isRecursive(const size_t scc) const
Return if the given SCC is recursive.
Relation * getRelation(const Program &program, const QualifiedName &name)
Returns the relation with the given name in the program.
std::vector< T * > getBodyLiterals(const C &clause)
Returns literals of a particular type in the body of a clause.
detail::joined_sequence< Iter, Printer > join(const Iter &a, const Iter &b, const std::string &sep, const Printer &p)
Creates an object to be forwarded to some output stream for printing sequences of elements interspers...
void addError(const std::string &message, SrcLocation location)
Adds an error with the given message and location.
std::set< const Relation *, NameComparison > RelationSet
Relation set.
std::vector< Relation * > getRelations() const
Return relations.
bool isInput(const Relation *relation) const
std::vector< Clause * > getClauses(const Program &program, const QualifiedName &relationName)
Returns a vector of clauses in the program describing the relation with the given name.
std::vector< Directive * > getDirectives() const
Return relation directives.
std::vector< std::string > splitString(const std::string &str, char delimiter)
Splits a string given a delimiter.
void addWarning(const std::string &message, SrcLocation location)
Adds a warning with the given message and location.
void visitDepthFirst(const Node &root, Visitor< R, Ps... > &visitor, Args &... args)
A utility function visiting all nodes within the ast rooted by the given node recursively in a depth-...
bool recursive(const Clause *clause) const
void addDiagnostic(const Diagnostic &diagnostic)
void rel(size_t limit, bool showLimit=true)
Program & getProgram() const
Return the program.
const std::set< const Relation * > & getInternalRelations(const size_t scc) const
Get all internal relations of a given SCC.
bool isPrimitiveType(const QualifiedName &identifier) const