souffle  2.0.2-371-g6315b36
TypeConstraints.cpp
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2020, The Souffle Developers. All rights reserved.
4  * Licensed under the Universal Permissive License v 1.0 as shown at:
5  * - https://opensource.org/licenses/UPL
6  * - <souffle root>/licenses/SOUFFLE-UPL.txt
7  */
8 
9 /************************************************************************
10  *
11  * @file TypeConstraints.cpp
12  *
13  ***********************************************************************/
14 
16 
17 namespace souffle::ast::analysis {
18 
19 /**
20  * A constraint factory ensuring that all the types associated to the variable
21  * a are subtypes of the variable b.
22  */
23 static TypeConstraint isSubtypeOf(const TypeVar& a, const TypeVar& b) {
24  return sub(a, b, "<:");
25 }
26 
27 /**
28  * A constraint factory ensuring that all the types associated to the variable
29  * a are subtypes of type b.
30  */
31 static TypeConstraint isSubtypeOf(const TypeVar& variable, const Type& type) {
32  struct C : public Constraint<TypeVar> {
33  TypeVar variable;
34  const Type& type;
35 
36  C(TypeVar variable, const Type& type) : variable(std::move(variable)), type(type) {}
37 
38  bool update(Assignment<TypeVar>& assignments) const override {
39  TypeSet& assignment = assignments[variable];
40 
41  if (assignment.isAll()) {
42  assignment = TypeSet(type);
43  return true;
44  }
45 
46  TypeSet newAssignment;
47  for (const Type& t : assignment) {
48  newAssignment.insert(getGreatestCommonSubtypes(t, type));
49  }
50 
51  // check whether there was a change
52  if (assignment == newAssignment) {
53  return false;
54  }
55  assignment = newAssignment;
56  return true;
57  }
58 
59  void print(std::ostream& out) const override {
60  out << variable << " <: " << type.getName();
61  }
62  };
63 
64  return std::make_shared<C>(variable, type);
65 }
66 
67 /**
68  * A constraint factory ensuring that all the types associated to the variable
69  * are subtypes of some type in the provided set (values)
70  *
71  * Values can't be all.
72  */
73 static TypeConstraint hasSuperTypeInSet(const TypeVar& var, TypeSet values) {
74  struct C : public Constraint<TypeVar> {
75  TypeVar var;
76  TypeSet values;
77 
78  C(TypeVar var, TypeSet values) : var(std::move(var)), values(std::move(values)) {}
79 
80  bool update(Assignment<TypeVar>& assigment) const override {
81  // get current value of variable a
82  TypeSet& assigments = assigment[var];
83 
84  // remove all types that are not sub-types of b
85  if (assigments.isAll()) {
86  assigments = values;
87  return true;
88  }
89 
90  TypeSet newAssigments;
91  for (const Type& type : assigments) {
92  bool existsSuperTypeInValues =
93  any_of(values, [&type](const Type& value) { return isSubtypeOf(type, value); });
94  if (existsSuperTypeInValues) {
95  newAssigments.insert(type);
96  }
97  }
98  // check whether there was a change
99  if (newAssigments == assigments) {
100  return false;
101  }
102  assigments = newAssigments;
103  return true;
104  }
105 
106  void print(std::ostream& out) const override {
107  out << "∃ t ∈ " << values << ": " << var << " <: t";
108  }
109  };
110 
111  return std::make_shared<C>(var, values);
112 }
113 
114 static const Type& getBaseType(const Type* type) {
115  while (auto subset = dynamic_cast<const SubsetType*>(type)) {
116  type = &subset->getBaseType();
117  };
118  assert((isA<ConstantType>(type) || isA<RecordType>(type)) &&
119  "Root must be a constant type or a record type");
120  return *type;
121 }
122 
123 /**
124  * Ensure that types of left and right have the same base types.
125  */
126 static TypeConstraint subtypesOfTheSameBaseType(const TypeVar& left, const TypeVar& right) {
127  struct C : public Constraint<TypeVar> {
128  TypeVar left;
129  TypeVar right;
130 
131  C(TypeVar left, TypeVar right) : left(std::move(left)), right(std::move(right)) {}
132 
133  bool update(Assignment<TypeVar>& assigment) const override {
134  // get current value of variable a
135  TypeSet& assigmentsLeft = assigment[left];
136  TypeSet& assigmentsRight = assigment[right];
137 
138  // Base types common to left and right variables.
139  TypeSet baseTypes;
140 
141  // Base types present in left/right variable.
142  TypeSet baseTypesLeft;
143  TypeSet baseTypesRight;
144 
145  // Iterate over possible types extracting base types.
146  // Left
147  if (!assigmentsLeft.isAll()) {
148  for (const Type& type : assigmentsLeft) {
149  if (isA<SubsetType>(type) || isA<ConstantType>(type)) {
150  baseTypesLeft.insert(getBaseType(&type));
151  }
152  }
153  }
154  // Right
155  if (!assigmentsRight.isAll()) {
156  for (const Type& type : assigmentsRight) {
157  if (isA<SubsetType>(type) || isA<ConstantType>(type)) {
158  baseTypesRight.insert(getBaseType(&type));
159  }
160  }
161  }
162 
163  TypeSet resultLeft;
164  TypeSet resultRight;
165 
166  // Handle all
167  if (assigmentsLeft.isAll() && assigmentsRight.isAll()) {
168  return false;
169  }
170 
171  // If left xor right is all, assign base types of the other side as possible values.
172  if (assigmentsLeft.isAll()) {
173  assigmentsLeft = baseTypesRight;
174  return true;
175  }
176  if (assigmentsRight.isAll()) {
177  assigmentsRight = baseTypesLeft;
178  return true;
179  }
180 
181  baseTypes = TypeSet::intersection(baseTypesLeft, baseTypesRight);
182 
183  // Allow types if they are subtypes of any of the common base types.
184  for (const Type& type : assigmentsLeft) {
185  bool isSubtypeOfCommonBaseType = any_of(baseTypes.begin(), baseTypes.end(),
186  [&type](const Type& baseType) { return isSubtypeOf(type, baseType); });
187  if (isSubtypeOfCommonBaseType) {
188  resultLeft.insert(type);
189  }
190  }
191 
192  for (const Type& type : assigmentsRight) {
193  bool isSubtypeOfCommonBaseType = any_of(baseTypes.begin(), baseTypes.end(),
194  [&type](const Type& baseType) { return isSubtypeOf(type, baseType); });
195  if (isSubtypeOfCommonBaseType) {
196  resultRight.insert(type);
197  }
198  }
199 
200  // check whether there was a change
201  if (resultLeft == assigmentsLeft && resultRight == assigmentsRight) {
202  return false;
203  }
204  assigmentsLeft = resultLeft;
205  assigmentsRight = resultRight;
206  return true;
207  }
208  //
209  void print(std::ostream& out) const override {
210  out << "∃ t : (" << left << " <: t)"
211  << " ∧ "
212  << "(" << right << " <: t)"
213  << " where t is a base type";
214  }
215  };
216 
217  return std::make_shared<C>(left, right);
218 }
219 
220 /**
221  * Given a set of overloads, wait the list of candidates to reduce to one and then apply its constraints.
222  * NOTE: `subtypeResult` implies that `func <: overload-return-type`, rather than
223  * `func = overload-return-type`. This is required for old type semantics.
224  * See #1296 and tests/semantic/type_system4
225  */
226 static TypeConstraint satisfiesOverload(const TypeEnvironment& typeEnv, IntrinsicFunctors overloads,
227  TypeVar result, std::vector<TypeVar> args, bool subtypeResult) {
228  struct C : public Constraint<TypeVar> {
229  // Check if there already was a non-monotonic update
230  mutable bool nonMonotonicUpdate = false;
231 
232  const TypeEnvironment& typeEnv;
233  mutable IntrinsicFunctors overloads;
234  TypeVar result;
235  std::vector<TypeVar> args;
236  bool subtypeResult;
237 
238  C(const TypeEnvironment& typeEnv, IntrinsicFunctors overloads, TypeVar result,
239  std::vector<TypeVar> args, bool subtypeResult)
240  : typeEnv(typeEnv), overloads(std::move(overloads)), result(std::move(result)),
241  args(std::move(args)), subtypeResult(subtypeResult) {}
242 
243  bool update(Assignment<TypeVar>& assigment) const override {
244  auto subtypesOf = [&](const TypeSet& src, TypeAttribute tyAttr) {
245  auto& ty = typeEnv.getConstantType(tyAttr);
246  return src.filter(TypeSet(true), [&](auto&& x) { return isSubtypeOf(x, ty); });
247  };
248 
249  auto possible = [&](TypeAttribute ty, const TypeVar& var) {
250  auto& curr = assigment[var];
251  return curr.isAll() || any_of(curr, [&](auto&& t) { return getTypeAttribute(t) == ty; });
252  };
253 
254  overloads = filterNot(std::move(overloads), [&](const IntrinsicFunctorInfo& x) -> bool {
255  if (!x.variadic && args.size() != x.params.size()) return true; // arity mismatch?
256 
257  for (size_t i = 0; i < args.size(); ++i) {
258  if (!possible(x.params[x.variadic ? 0 : i], args[i])) return true;
259  }
260 
261  return !possible(x.result, result);
262  });
263 
264  bool changed = false;
265  auto newResult = [&]() -> std::optional<TypeSet> {
266  if (0 == overloads.size()) return TypeSet();
267  if (1 < overloads.size()) return {};
268 
269  auto& overload = overloads.front().get();
270  // `ord` is freakin' magical: it has the signature `a -> Int`.
271  // As a consequence, we might be given non-primitive arguments (i.e. types for which
272  // `TypeEnv::getConstantType` is undefined).
273  // Handle this by not imposing constraints on the arguments.
274  if (overload.op != FunctorOp::ORD) {
275  for (size_t i = 0; i < args.size(); ++i) {
276  auto argTy = overload.params[overload.variadic ? 0 : i];
277  auto& currArg = assigment[args[i]];
278  auto newArg = subtypesOf(currArg, argTy);
279  changed |= currArg != newArg;
280  // 2020-05-09: CI linter says to remove `std::move`, but clang-tidy-10 is happy.
281  currArg = std::move(newArg); // NOLINT
282  }
283  }
284 
285  if (nonMonotonicUpdate || subtypeResult) {
286  return subtypesOf(assigment[result], overload.result);
287  } else {
288  nonMonotonicUpdate = true;
289  return TypeSet{typeEnv.getConstantType(overload.result)};
290  }
291  }();
292 
293  if (newResult) {
294  auto& curr = assigment[result];
295  changed |= curr != *newResult;
296  // 2020-05-09: CI linter says to remove `std::move`, but clang-tidy-10 is happy.
297  curr = std::move(*newResult); // NOLINT
298  }
299 
300  return changed;
301  }
302 
303  void print(std::ostream& out) const override {
304  // TODO (darth_tytus): is this description correct?
305  out << "∃ t : " << result << " <: t where t is a base type";
306  }
307  };
308 
309  return std::make_shared<C>(
310  typeEnv, std::move(overloads), std::move(result), std::move(args), subtypeResult);
311 }
312 
313 /**
314  * Constraint on record type and its elements.
315  */
317  const TypeVar& elementVariable, const TypeVar& recordVariable, size_t index) {
318  struct C : public Constraint<TypeVar> {
319  TypeVar elementVariable;
320  TypeVar recordVariable;
321  unsigned index;
322 
323  C(TypeVar elementVariable, TypeVar recordVariable, int index)
324  : elementVariable(std::move(elementVariable)), recordVariable(std::move(recordVariable)),
325  index(index) {}
326 
327  bool update(Assignment<TypeVar>& assignment) const override {
328  // get list of types for b
329  const TypeSet& recordTypes = assignment[recordVariable];
330 
331  // if it is (not yet) constrainted => skip
332  if (recordTypes.isAll()) {
333  return false;
334  }
335 
336  // compute new types for element and record
337  TypeSet newElementTypes;
338  TypeSet newRecordTypes;
339 
340  for (const Type& type : recordTypes) {
341  // A type must be either a record type or a subset of a record type
343  continue;
344  }
345 
346  const auto& typeAsRecord = *as<RecordType>(type);
347 
348  // Wrong size => skip.
349  if (typeAsRecord.getFields().size() <= index) {
350  continue;
351  }
352 
353  // Valid type for record.
354  newRecordTypes.insert(type);
355 
356  // and its corresponding field.
357  newElementTypes.insert(*typeAsRecord.getFields()[index]);
358  }
359 
360  // combine with current types assigned to element
361  newElementTypes = getGreatestCommonSubtypes(assignment[elementVariable], newElementTypes);
362 
363  // update values
364  bool changed = false;
365  if (newRecordTypes != recordTypes) {
366  assignment[recordVariable] = newRecordTypes;
367  changed = true;
368  }
369 
370  if (assignment[elementVariable] != newElementTypes) {
371  assignment[elementVariable] = newElementTypes;
372  changed = true;
373  }
374 
375  return changed;
376  }
377 
378  void print(std::ostream& out) const override {
379  out << elementVariable << " <: " << recordVariable << "::" << index;
380  }
381  };
382 
383  return std::make_shared<C>(elementVariable, recordVariable, index);
384 }
385 
386 void TypeConstraintsAnalysis::visitSink(const Atom& atom) {
387  iterateOverAtom(atom, [&](const Argument& argument, const Type& attributeType) {
388  if (isA<RecordType>(attributeType)) {
389  addConstraint(isSubtypeOf(getVar(argument), getBaseType(&attributeType)));
390  return;
391  }
392  for (auto& constantType : typeEnv.getConstantTypes()) {
393  if (isSubtypeOf(attributeType, constantType)) {
394  addConstraint(isSubtypeOf(getVar(argument), constantType));
395  }
396  }
397  });
398 }
399 
400 void TypeConstraintsAnalysis::visitAtom(const Atom& atom) {
401  if (contains(sinks, &atom)) {
402  visitSink(atom);
403  return;
404  }
405 
406  iterateOverAtom(atom, [&](const Argument& argument, const Type& attributeType) {
407  addConstraint(isSubtypeOf(getVar(argument), attributeType));
408  });
409 }
410 
411 void TypeConstraintsAnalysis::visitNegation(const Negation& cur) {
412  sinks.insert(cur.getAtom());
413 }
414 
417 }
418 
420  TypeSet possibleTypes;
421 
422  // Check if the type is given.
423  if (constant.getFixedType().has_value()) {
424  switch (constant.getFixedType().value()) {
425  // Insert a type, but only after checking that parsing is possible.
427  if (canBeParsedAsRamSigned(constant.getConstant())) {
429  }
430  break;
432  if (canBeParsedAsRamUnsigned(constant.getConstant())) {
434  }
435  break;
437  if (canBeParsedAsRamFloat(constant.getConstant())) {
439  }
440  break;
441  }
442  } else if (contains(typeAnalysis.getNumericConstantTypes(), &constant)) {
443  switch (typeAnalysis.getNumericConstantTypes().at(&constant)) {
444  // Insert a type, but only after checking that parsing is possible.
446  if (canBeParsedAsRamSigned(constant.getConstant())) {
448  }
449  break;
451  if (canBeParsedAsRamUnsigned(constant.getConstant())) {
453  }
454  break;
456  if (canBeParsedAsRamFloat(constant.getConstant())) {
458  }
459  break;
460  }
461  } else {
462  // Else: all numeric types that can be parsed are valid.
463  if (canBeParsedAsRamSigned(constant.getConstant())) {
465  }
466 
467  if (canBeParsedAsRamUnsigned(constant.getConstant())) {
469  }
470 
471  if (canBeParsedAsRamFloat(constant.getConstant())) {
473  }
474  }
475 
476  addConstraint(hasSuperTypeInSet(getVar(constant), possibleTypes));
477 }
478 
479 void TypeConstraintsAnalysis::visitBinaryConstraint(const BinaryConstraint& rel) {
480  auto lhs = getVar(rel.getLHS());
481  auto rhs = getVar(rel.getRHS());
484 }
485 
487  auto functorVar = getVar(fun);
488 
489  auto intrFun = as<IntrinsicFunctor>(fun);
490  if (intrFun) {
491  auto argVars = map(intrFun->getArguments(), [&](auto&& x) { return getVar(x); });
492  // The type of the user-defined function might not be set at this stage.
493  // If so then add overloads as alternatives
494  if (!typeAnalysis.hasValidTypeInfo(intrFun))
495  addConstraint(satisfiesOverload(typeEnv, functorBuiltIn(intrFun->getBaseFunctionOp()), functorVar,
496  argVars, isInfixFunctorOp(intrFun->getBaseFunctionOp())));
497 
498  // In polymorphic case
499  // We only require arguments to share a base type with a return type.
500  // (instead of, for example, requiring them to be of the same type)
501  // This approach is related to old type semantics
502  // See #1296 and tests/semantic/type_system4
503  if (isInfixFunctorOp(intrFun->getBaseFunctionOp())) {
504  for (auto&& var : argVars)
505  addConstraint(subtypesOfTheSameBaseType(var, functorVar));
506 
507  return;
508  }
509 
510  if (!typeAnalysis.hasValidTypeInfo(intrFun)) {
511  return;
512  }
513  }
514 
515  // Skip constraint adding if type info is not available
516  if (!typeAnalysis.hasValidTypeInfo(&fun)) {
517  return;
518  }
519 
520  // add a constraint for the return type of the functor
522  addConstraint(isSubtypeOf(functorVar, typeEnv.getConstantType(returnType)));
523  // Special case. Ord returns the ram representation of any object.
524  if (intrFun && typeAnalysis.getPolymorphicOperator(intrFun) == FunctorOp::ORD) {
525  return;
526  }
527 
528  // Add constraints on arguments
529  auto arguments = fun.getArguments();
530  for (size_t i = 0; i < arguments.size(); ++i) {
532  addConstraint(isSubtypeOf(getVar(arguments[i]), typeEnv.getConstantType(argType)));
533  }
534 }
535 
536 void TypeConstraintsAnalysis::visitCounter(const Counter& counter) {
538 }
539 
541  auto& typeName = typeCast.getType();
542  if (!typeEnv.isType(typeName)) {
543  return;
544  }
545 
546  addConstraint(isSubtypeOf(getVar(typeCast), typeEnv.getType(typeName)));
547 
548  // If we are dealing with a constant then its type must be deduced from the cast
549  // Otherwise, expression like: to_string(as(2, float)) couldn't be typed.
550  auto* value = typeCast.getValue();
551 
552  if (isA<Constant>(value)) {
553  addConstraint(isSubtypeOf(getVar(*value), typeEnv.getType(typeName)));
554  }
555 }
556 
557 void TypeConstraintsAnalysis::visitRecordInit(const RecordInit& record) {
558  auto arguments = record.getArguments();
559  for (size_t i = 0; i < arguments.size(); ++i) {
560  addConstraint(isSubtypeOfComponent(getVar(arguments[i]), getVar(record), i));
561  }
562 }
563 
565  auto* correspondingType = sumTypesBranches.getType(adt.getConstructor());
566 
567  if (correspondingType == nullptr) {
568  return; // malformed program.
569  }
570 
571  // Sanity check
572  assert(isA<AlgebraicDataType>(correspondingType));
573 
574  // Constraint on the whole branch. $Branch(...) <: ADTtype
575  addConstraint(isSubtypeOf(getVar(adt), *correspondingType));
576 
577  // Constraints on arguments
578  auto branchTypes = as<AlgebraicDataType>(correspondingType)->getBranchTypes(adt.getConstructor());
579  auto branchArgs = adt.getArguments();
580 
581  if (branchTypes.size() != branchArgs.size()) {
582  // invalid program - handled by semantic checker later.
583  return;
584  }
585 
586  // Add constraints for each of the branch arguments.
587  for (size_t i = 0; i < branchArgs.size(); ++i) {
588  auto argVar = getVar(branchArgs[i]);
589  addConstraint(isSubtypeOf(argVar, *branchTypes[i]));
590  }
591 }
592 
593 void TypeConstraintsAnalysis::visitAggregator(const Aggregator& agg) {
594  if (agg.getBaseOperator() == AggregateOp::COUNT) {
596  } else if (agg.getBaseOperator() == AggregateOp::MEAN) {
598  } else {
600  }
601 
602  // If there is a target expression - it should be of the same type as the aggregator.
603  if (auto expr = agg.getTargetExpression()) {
604  addConstraint(isSubtypeOf(getVar(expr), getVar(agg)));
605  addConstraint(isSubtypeOf(getVar(agg), getVar(expr)));
606  }
607 }
608 
610  const Atom& atom, std::function<void(const Argument&, const Type&)> map) {
611  // get relation
612  auto rel = getAtomRelation(&atom, &program);
613  if (rel == nullptr) {
614  return; // error in input program
615  }
616 
617  auto atts = rel->getAttributes();
618  auto args = atom.getArguments();
619  if (atts.size() != args.size()) {
620  return; // error in input program
621  }
622 
623  for (size_t i = 0; i < atts.size(); i++) {
624  const auto& typeName = atts[i]->getTypeName();
625  if (typeEnv.isType(typeName)) {
626  map(*args[i], typeEnv.getType(typeName));
627  }
628  }
629 }
630 
631 void TypeConstraintsAnalysis::collectConstraints(const Clause& clause) {
632  sinks.insert(clause.getHead());
633  visitDepthFirstPreOrder(clause, *this);
634 }
635 
636 } // namespace souffle::ast::analysis
souffle::ast::analysis::isOfKind
bool isOfKind(const Type &type, TypeAttribute kind)
Check if the type is of a kind corresponding to the TypeAttribute.
Definition: TypeSystem.cpp:189
souffle::TypeAttribute::Record
@ Record
souffle::ast::analysis::hasSuperTypeInSet
static TypeConstraint hasSuperTypeInSet(const TypeVar &var, TypeSet values)
A constraint factory ensuring that all the types associated to the variable are subtypes of some type...
Definition: TypeConstraints.cpp:77
souffle::ast::analysis::ConstraintAnalysis< TypeVar >::getVar
TypeVar getVar(const Argument &arg)
A utility function mapping an Argument to its associated analysis variable.
Definition: Constraint.h:106
souffle::ast::analysis::TypeConstraintsAnalysis::visitTypeCast
void visitTypeCast(const ast::TypeCast &typeCast) override
Definition: TypeConstraints.cpp:544
TypeAttribute
Type attribute class.
souffle::filterNot
std::vector< A > filterNot(std::vector< A > xs, F &&f)
Filter a vector to exclude certain elements.
Definition: FunctionalUtil.h:146
souffle::ast::analysis::TypeAnalysis::getPolymorphicOperator
AggregateOp getPolymorphicOperator(const Aggregator *agg) const
Definition: Type.cpp:278
souffle::ast::analysis::sub
std::shared_ptr< Constraint< Var > > sub(const Var &a, const Var &b, const std::string &symbol="⊑")
A generic factory for constraints of the form.
Definition: ConstraintSystem.h:228
souffle::ast::NumericConstant::getFixedType
const std::optional< Type > & getFixedType() const
Definition: NumericConstant.h:73
souffle::canBeParsedAsRamFloat
bool canBeParsedAsRamFloat(const std::string &string)
Can a string be parsed as RamFloat.
Definition: StringUtil.h:192
souffle::ast::analysis::TypeEnvironment::getType
const Type & getType(const QualifiedName &) const
Definition: TypeSystem.cpp:81
souffle::ast::analysis::TypeSet::insert
void insert(const Type &type)
Adds the given type to this set.
Definition: TypeSystem.h:288
souffle::ast::analysis::TypeSet::intersection
static TypeSet intersection(const TypeSet &left, const TypeSet &right)
Calculate intersection of two TypeSet.
Definition: TypeSystem.h:295
souffle::ast::analysis::ConstraintAnalysisVar
A variable type to be utilized by AST constraint analysis.
Definition: Constraint.h:45
souffle::ast::analysis::TypeSet::end
const_iterator end() const
Allows to iterate over the types contained in this set (only if not universal)
Definition: TypeSystem.h:349
souffle::contains
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.
Definition: ContainerUtil.h:75
souffle::TypeAttribute::Symbol
@ Symbol
souffle::ast::TypeCast::getType
const QualifiedName & getType() const
Return cast type.
Definition: TypeCast.h:57
souffle::map
auto map(const std::vector< A > &xs, F &&f)
Applies a function to each element of a vector and returns the results.
Definition: ContainerUtil.h:158
souffle::ast::analysis::TypeConstraintsAnalysis::visitFunctor
void visitFunctor(const Functor &fun) override
Definition: TypeConstraints.cpp:490
souffle::ast::analysis::getBaseType
static const Type & getBaseType(const Type *type)
Definition: TypeConstraints.cpp:118
souffle::ast::Constant::getConstant
const std::string & getConstant() const
Get string representation of Constant.
Definition: Constant.h:43
souffle::ast::analysis::TypeEnvironment::isType
bool isType(const QualifiedName &) const
Definition: TypeSystem.cpp:73
souffle::ast::analysis::Type
An abstract base class for types to be covered within a type environment.
Definition: TypeSystem.h:51
souffle::FunctorOp::ORD
@ ORD
Unary Functor Operators.
rhs
Own< Argument > rhs
Definition: ResolveAliases.cpp:185
souffle::ast::analysis::TypeAnalysis::hasValidTypeInfo
bool hasValidTypeInfo(const Argument *argument) const
Definition: Type.cpp:255
souffle::ast::analysis::TypeSet
A collection to represent sets of types.
Definition: TypeSystem.h:249
souffle::ast::analysis::TypeConstraintsAnalysis::visitCounter
void visitCounter(const Counter &counter) override
Definition: TypeConstraints.cpp:540
souffle::TypeAttribute::Signed
@ Signed
souffle::ast::NumericConstant::Type::Int
@ Int
souffle::IntrinsicFunctors
std::vector< std::reference_wrapper< const IntrinsicFunctorInfo > > IntrinsicFunctors
Definition: FunctorOps.h:129
souffle::ast::analysis::getGreatestCommonSubtypes
TypeSet getGreatestCommonSubtypes(const Type &a, const Type &b)
Computes the greatest common sub types of the two given types.
Definition: TypeSystem.cpp:254
souffle::ast::Argument
An abstract class for arguments.
Definition: Argument.h:33
souffle::ast::analysis::TypeAnalysis::getFunctorReturnType
TypeAttribute getFunctorReturnType(const Functor *functor) const
Definition: Type.cpp:145
souffle::ast::analysis::Constraint
A generic base class for constraints on variables.
Definition: ConstraintSystem.h:44
lhs
Own< Argument > lhs
Definition: ResolveAliases.cpp:184
souffle::ast::analysis::TypeConstraintsAnalysis::typeAnalysis
const TypeAnalysis & typeAnalysis
Definition: TypeConstraints.h:95
souffle::ast::analysis::TypeSet::begin
const_iterator begin() const
Allows to iterate over the types contained in this set (only if not universal)
Definition: TypeSystem.h:343
souffle::ast::analysis::isSubtypeOf
static TypeConstraint isSubtypeOf(const TypeVar &a, const TypeVar &b)
A constraint factory ensuring that all the types associated to the variable a are subtypes of the var...
Definition: TypeConstraints.cpp:27
souffle::TypeAttribute::Unsigned
@ Unsigned
i
size_t i
Definition: json11.h:663
souffle::ast::analysis::TypeConstraintsAnalysis::visitBinaryConstraint
void visitBinaryConstraint(const BinaryConstraint &rel) override
Definition: TypeConstraints.cpp:483
souffle::ast::analysis::TypeConstraintsAnalysis::visitSink
void visitSink(const Atom &atom)
Definition: TypeConstraints.cpp:390
souffle::ast::BranchInit::getConstructor
const std::string & getConstructor() const
Definition: BranchInit.h:54
souffle::ast::TypeCast
Defines a type cast class for expressions.
Definition: TypeCast.h:46
souffle::ast::analysis::TypeConstraintsAnalysis::typeEnv
const TypeEnvironment & typeEnv
Definition: TypeConstraints.h:92
souffle::ast::analysis::getTypeAttribute
TypeAttribute getTypeAttribute(const Type &type)
Definition: TypeSystem.cpp:353
souffle::ast::analysis::ConstraintAnalysis< TypeVar >::addConstraint
void addConstraint(const constraint_type &constraint)
Adds another constraint to the internally maintained list of constraints.
Definition: Constraint.h:129
souffle::ast::analysis::TypeConstraintsAnalysis::visitStringConstant
void visitStringConstant(const StringConstant &cnst) override
Definition: TypeConstraints.cpp:419
souffle::any_of
bool any_of(const Container &c, UnaryPredicate p)
A generic test checking whether any elements within a container satisfy a certain predicate.
Definition: FunctionalUtil.h:124
TypeConstraints.h
souffle::ast::analysis::TypeEnvironment
A type environment is a set of types.
Definition: TypeSystem.h:401
souffle::ast::analysis::TypeConstraint
std::shared_ptr< Constraint< TypeVar > > TypeConstraint
The definition of the type of constraint to be utilized in the type analysis.
Definition: TypeConstraints.h:75
souffle::ast::analysis::TypeEnvironment::getConstantType
const Type & getConstantType(TypeAttribute type) const
Definition: TypeSystem.h:424
souffle::ast::analysis::Assignment< TypeVar >
souffle::ast::visitDepthFirstPreOrder
void visitDepthFirstPreOrder(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-...
Definition: Visitor.h:235
souffle::ast::analysis::isSubtypeOfComponent
static TypeConstraint isSubtypeOfComponent(const TypeVar &elementVariable, const TypeVar &recordVariable, size_t index)
Constraint on record type and its elements.
Definition: TypeConstraints.cpp:320
souffle::canBeParsedAsRamUnsigned
bool canBeParsedAsRamUnsigned(const std::string &string)
Can a string be parsed as RamUnsigned.
Definition: StringUtil.h:179
souffle::ast::analysis::TypeEnvironment::getConstantTypes
const TypeSet & getConstantTypes() const
Definition: TypeSystem.h:448
souffle::ast::analysis::satisfiesOverload
static TypeConstraint satisfiesOverload(const TypeEnvironment &typeEnv, IntrinsicFunctors overloads, TypeVar result, std::vector< TypeVar > args, bool subtypeResult)
Given a set of overloads, wait the list of candidates to reduce to one and then apply its constraints...
Definition: TypeConstraints.cpp:230
souffle::ast::Term::getArguments
std::vector< Argument * > getArguments() const
Get arguments.
Definition: Term.h:56
souffle::ast::Functor
Abstract functor class.
Definition: Functor.h:36
souffle::ast::analysis::subtypesOfTheSameBaseType
static TypeConstraint subtypesOfTheSameBaseType(const TypeVar &left, const TypeVar &right)
Ensure that types of left and right have the same base types.
Definition: TypeConstraints.cpp:130
souffle::ast::analysis::TypeSet::isAll
bool isAll() const
Universality check.
Definition: TypeSystem.h:272
souffle::ast::analysis::TypeConstraintsAnalysis::sinks
std::set< const Atom * > sinks
Definition: TypeConstraints.h:98
souffle::ast::analysis::TypeEnvironment::getConstantNumericTypes
const TypeSet & getConstantNumericTypes() const
Definition: TypeSystem.h:456
souffle::ast::analysis::TypeAnalysis::getFunctorArgType
TypeAttribute getFunctorArgType(const Functor *functor, const size_t idx) const
Definition: Type.cpp:155
souffle::AggregateOp::COUNT
@ COUNT
souffle::ast::analysis::TypeSet::filter
TypeSet filter(TypeSet whenAll, F &&f) const
Definition: TypeSystem.h:314
souffle::functorBuiltIn
IntrinsicFunctors functorBuiltIn(FunctorOp op)
Definition: FunctorOps.cpp:224
souffle::AggregateOp::MEAN
@ MEAN
b
l j a showGridBackground &&c b raw series this eventEmitter b
Definition: htmlJsChartistMin.h:15
std
Definition: Brie.h:3053
souffle::ast::TypeCast::getValue
Argument * getValue() const
Return value.
Definition: TypeCast.h:52
souffle::ast::analysis::TypeConstraintsAnalysis::visitNegation
void visitNegation(const Negation &cur) override
Definition: TypeConstraints.cpp:415
souffle::canBeParsedAsRamSigned
bool canBeParsedAsRamSigned(const std::string &string)
Can a string be parsed as RamSigned.
Definition: StringUtil.h:162
souffle::ast::analysis::TypeConstraintsAnalysis::visitNumericConstant
void visitNumericConstant(const NumericConstant &constant) override
Definition: TypeConstraints.cpp:423
souffle::ast::analysis::TypeAnalysis::getNumericConstantTypes
const std::map< const NumericConstant *, NumericConstant::Type > & getNumericConstantTypes() const
Definition: Type.cpp:174
souffle::ast::NumericConstant::Type::Uint
@ Uint
souffle::ast::analysis::TypeConstraintsAnalysis::sumTypesBranches
const SumTypeBranchesAnalysis & sumTypesBranches
Definition: TypeConstraints.h:94
souffle::ast::analysis::TypeConstraintsAnalysis::collectConstraints
void collectConstraints(const Clause &clause) override
Visitors.
Definition: TypeConstraints.cpp:635
souffle::ast::analysis
Definition: Aggregate.cpp:39
souffle::ast::analysis::TypeConstraintsAnalysis::visitBranchInit
void visitBranchInit(const BranchInit &adt) override
Definition: TypeConstraints.cpp:568
souffle::ast::BranchInit
Initialization of ADT instance.
Definition: BranchInit.h:49
souffle::ast::getAtomRelation
const Relation * getAtomRelation(const Atom *atom, const Program *program)
Returns the relation referenced by the given atom.
Definition: Utils.cpp:129
souffle::ast::analysis::TypeConstraintsAnalysis::visitAggregator
void visitAggregator(const Aggregator &agg) override
Definition: TypeConstraints.cpp:597
souffle::isInfixFunctorOp
bool isInfixFunctorOp(std::string_view symbol)
Determines whether a functor should be written using infix notation (e.g.
Definition: FunctorOps.cpp:252
souffle::ast::NumericConstant::Type::Float
@ Float
souffle::ast::analysis::TypeConstraintsAnalysis::iterateOverAtom
void iterateOverAtom(const Atom &atom, std::function< void(const Argument &, const Type &)> map)
Utility function.
Definition: TypeConstraints.cpp:613
souffle::ast::NumericConstant
Numeric Constant.
Definition: NumericConstant.h:43
souffle::TypeAttribute::Float
@ Float
rel
void rel(size_t limit, bool showLimit=true)
Definition: Tui.h:1086
souffle::ast::analysis::SumTypeBranchesAnalysis::getType
const Type * getType(const std::string &branch) const
A type can be nullptr in case of a malformed program.
Definition: SumTypeBranches.h:57
souffle::ast::analysis::TypeConstraintsAnalysis::visitRecordInit
void visitRecordInit(const RecordInit &record) override
Definition: TypeConstraints.cpp:561
souffle::ast::StringConstant
String constant class.
Definition: StringConstant.h:37
souffle::ast::analysis::TypeVar
ConstraintAnalysisVar< type_lattice > TypeVar
The definition of the type of variable to be utilized in the type analysis.
Definition: TypeConstraints.h:72
souffle::ast::analysis::TypeConstraintsAnalysis::program
const Program & program
Definition: TypeConstraints.h:93
std::type
ElementType type
Definition: span.h:640
souffle::ast::analysis::TypeConstraintsAnalysis::visitAtom
void visitAtom(const Atom &atom) override
Definition: TypeConstraints.cpp:404