| souffle
    2.0.2-371-g6315b36
    | 
 
 
 
Go to the documentation of this file.
   24     return sub(a, 
b, 
"<:");
 
   39             TypeSet& assignment = assignments[variable];
 
   41             if (assignment.
isAll()) {
 
   46             TypeSet newAssignment;
 
   47             for (
const Type& t : assignment) {
 
   52             if (assignment == newAssignment) {
 
   55             assignment = newAssignment;
 
   59         void print(std::ostream& out)
 const override {
 
   60             out << variable << 
" <: " << 
type.getName();
 
   64     return std::make_shared<C>(variable, 
type);
 
   74     struct C : 
public Constraint<TypeVar> {
 
   82             TypeSet& assigments = assigment[var];
 
   85             if (assigments.
isAll()) {
 
   90             TypeSet newAssigments;
 
   91             for (
const Type& 
type : assigments) {
 
   92                 bool existsSuperTypeInValues =
 
   94                 if (existsSuperTypeInValues) {
 
   95                     newAssigments.insert(
type);
 
   99             if (newAssigments == assigments) {
 
  102             assigments = newAssigments;
 
  106         void print(std::ostream& out)
 const override {
 
  107             out << 
"∃ t ∈ " << values << 
": " << var << 
" <: t";
 
  111     return std::make_shared<C>(var, values);
 
  115     while (
auto subset = 
dynamic_cast<const SubsetType*
>(
type)) {
 
  116         type = &subset->getBaseType();
 
  118     assert((isA<ConstantType>(
type) || isA<RecordType>(
type)) &&
 
  119             "Root must be a constant type or a record type");
 
  135             TypeSet& assigmentsLeft = assigment[left];
 
  136             TypeSet& assigmentsRight = assigment[right];
 
  147             if (!assigmentsLeft.
isAll()) {
 
  148                 for (
const Type& 
type : assigmentsLeft) {
 
  149                     if (isA<SubsetType>(
type) || isA<ConstantType>(
type)) {
 
  155             if (!assigmentsRight.
isAll()) {
 
  156                 for (
const Type& 
type : assigmentsRight) {
 
  157                     if (isA<SubsetType>(
type) || isA<ConstantType>(
type)) {
 
  167             if (assigmentsLeft.isAll() && assigmentsRight.isAll()) {
 
  172             if (assigmentsLeft.isAll()) {
 
  173                 assigmentsLeft = baseTypesRight;
 
  176             if (assigmentsRight.isAll()) {
 
  177                 assigmentsRight = baseTypesLeft;
 
  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);
 
  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);
 
  201             if (resultLeft == assigmentsLeft && resultRight == assigmentsRight) {
 
  204             assigmentsLeft = resultLeft;
 
  205             assigmentsRight = resultRight;
 
  209         void print(std::ostream& out)
 const override {
 
  210             out << 
"∃ t : (" << left << 
" <: t)" 
  212                 << 
"(" << right << 
" <: t)" 
  213                 << 
" where t is a base type";
 
  217     return std::make_shared<C>(left, right);
 
  227         TypeVar result, std::vector<TypeVar> args, 
bool subtypeResult) {
 
  228     struct C : 
public Constraint<TypeVar> {
 
  230         mutable bool nonMonotonicUpdate = 
false;
 
  235         std::vector<TypeVar> args;
 
  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) {}
 
  250                 auto& curr = assigment[var];
 
  254             overloads = 
filterNot(std::move(overloads), [&](
const IntrinsicFunctorInfo& x) -> 
bool {
 
  255                 if (!x.variadic && args.size() != x.params.size()) 
return true;  
 
  257                 for (
size_t i = 0; 
i < args.size(); ++
i) {
 
  258                     if (!possible(x.params[x.variadic ? 0 : 
i], args[
i])) 
return true;
 
  261                 return !possible(x.result, result);
 
  264             bool changed = 
false;
 
  265             auto newResult = [&]() -> std::optional<TypeSet> {
 
  266                 if (0 == overloads.size()) 
return TypeSet();
 
  267                 if (1 < overloads.size()) 
return {};
 
  269                 auto& overload = overloads.front().get();
 
  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;
 
  281                         currArg = std::move(newArg);  
 
  285                 if (nonMonotonicUpdate || subtypeResult) {
 
  286                     return subtypesOf(assigment[result], overload.result);
 
  288                     nonMonotonicUpdate = 
true;
 
  294                 auto& curr = assigment[result];
 
  295                 changed |= curr != *newResult;
 
  297                 curr = std::move(*newResult);  
 
  303         void print(std::ostream& out)
 const override {
 
  305             out << 
"∃ t : " << result << 
" <: t where t is a base type";
 
  309     return std::make_shared<C>(
 
  310             typeEnv, std::move(overloads), std::move(result), std::move(args), subtypeResult);
 
  317         const TypeVar& elementVariable, 
const TypeVar& recordVariable, 
size_t index) {
 
  318     struct C : 
public Constraint<TypeVar> {
 
  324                 : elementVariable(
std::move(elementVariable)), recordVariable(
std::move(recordVariable)),
 
  329             const TypeSet& recordTypes = assignment[recordVariable];
 
  332             if (recordTypes.
isAll()) {
 
  337             TypeSet newElementTypes;
 
  338             TypeSet newRecordTypes;
 
  340             for (
const Type& 
type : recordTypes) {
 
  346                 const auto& typeAsRecord = *as<RecordType>(
type);
 
  349                 if (typeAsRecord.getFields().size() <= index) {
 
  354                 newRecordTypes.insert(
type);
 
  357                 newElementTypes.insert(*typeAsRecord.getFields()[index]);
 
  364             bool changed = 
false;
 
  365             if (newRecordTypes != recordTypes) {
 
  366                 assignment[recordVariable] = newRecordTypes;
 
  370             if (assignment[elementVariable] != newElementTypes) {
 
  371                 assignment[elementVariable] = newElementTypes;
 
  378         void print(std::ostream& out)
 const override {
 
  379             out << elementVariable << 
" <: " << recordVariable << 
"::" << index;
 
  383     return std::make_shared<C>(elementVariable, recordVariable, index);
 
  387     iterateOverAtom(atom, [&](
const Argument& argument, 
const Type& attributeType) {
 
  388         if (isA<RecordType>(attributeType)) {
 
  412     sinks.insert(cur.getAtom());
 
  487     auto functorVar = 
getVar(fun);
 
  489     auto intrFun = as<IntrinsicFunctor>(fun);
 
  491         auto argVars = 
map(intrFun->getArguments(), [&](
auto&& x) { return getVar(x); });
 
  504             for (
auto&& var : argVars)
 
  530     for (
size_t i = 0; 
i < arguments.size(); ++
i) {
 
  541     auto& typeName = typeCast.
getType();
 
  552     if (isA<Constant>(value)) {
 
  558     auto arguments = record.getArguments();
 
  559     for (
size_t i = 0; 
i < arguments.size(); ++
i) {
 
  567     if (correspondingType == 
nullptr) {
 
  572     assert(isA<AlgebraicDataType>(correspondingType));
 
  578     auto branchTypes = as<AlgebraicDataType>(correspondingType)->getBranchTypes(adt.
getConstructor());
 
  581     if (branchTypes.size() != branchArgs.size()) {
 
  587     for (
size_t i = 0; 
i < branchArgs.size(); ++
i) {
 
  588         auto argVar = 
getVar(branchArgs[
i]);
 
  603     if (
auto expr = agg.getTargetExpression()) {
 
  610         const Atom& atom, std::function<
void(
const Argument&, 
const Type&)> 
map) {
 
  617     auto atts = 
rel->getAttributes();
 
  618     auto args = atom.getArguments();
 
  619     if (atts.size() != args.size()) {
 
  623     for (
size_t i = 0; 
i < atts.size(); 
i++) {
 
  624         const auto& typeName = atts[
i]->getTypeName();
 
  632     sinks.insert(clause.getHead());
 
  
bool isOfKind(const Type &type, TypeAttribute kind)
Check if the type is of a kind corresponding to the TypeAttribute.
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...
TypeVar getVar(const Argument &arg)
A utility function mapping an Argument to its associated analysis variable.
void visitTypeCast(const ast::TypeCast &typeCast) override
std::vector< A > filterNot(std::vector< A > xs, F &&f)
Filter a vector to exclude certain elements.
AggregateOp getPolymorphicOperator(const Aggregator *agg) const
std::shared_ptr< Constraint< Var > > sub(const Var &a, const Var &b, const std::string &symbol="⊑")
A generic factory for constraints of the form.
const std::optional< Type > & getFixedType() const
bool canBeParsedAsRamFloat(const std::string &string)
Can a string be parsed as RamFloat.
const Type & getType(const QualifiedName &) const
void insert(const Type &type)
Adds the given type to this set.
static TypeSet intersection(const TypeSet &left, const TypeSet &right)
Calculate intersection of two TypeSet.
A variable type to be utilized by AST constraint analysis.
const_iterator end() const
Allows to iterate over the types contained in this set (only if not universal)
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.
const QualifiedName & getType() const
Return cast type.
auto map(const std::vector< A > &xs, F &&f)
Applies a function to each element of a vector and returns the results.
void visitFunctor(const Functor &fun) override
static const Type & getBaseType(const Type *type)
const std::string & getConstant() const
Get string representation of Constant.
bool isType(const QualifiedName &) const
An abstract base class for types to be covered within a type environment.
@ ORD
Unary Functor Operators.
bool hasValidTypeInfo(const Argument *argument) const
A collection to represent sets of types.
void visitCounter(const Counter &counter) override
std::vector< std::reference_wrapper< const IntrinsicFunctorInfo > > IntrinsicFunctors
TypeSet getGreatestCommonSubtypes(const Type &a, const Type &b)
Computes the greatest common sub types of the two given types.
An abstract class for arguments.
TypeAttribute getFunctorReturnType(const Functor *functor) const
A generic base class for constraints on variables.
const TypeAnalysis & typeAnalysis
const_iterator begin() const
Allows to iterate over the types contained in this set (only if not universal)
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...
void visitBinaryConstraint(const BinaryConstraint &rel) override
void visitSink(const Atom &atom)
const std::string & getConstructor() const
Defines a type cast class for expressions.
const TypeEnvironment & typeEnv
TypeAttribute getTypeAttribute(const Type &type)
void addConstraint(const constraint_type &constraint)
Adds another constraint to the internally maintained list of constraints.
void visitStringConstant(const StringConstant &cnst) override
bool any_of(const Container &c, UnaryPredicate p)
A generic test checking whether any elements within a container satisfy a certain predicate.
A type environment is a set of types.
std::shared_ptr< Constraint< TypeVar > > TypeConstraint
The definition of the type of constraint to be utilized in the type analysis.
const Type & getConstantType(TypeAttribute type) const
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-...
static TypeConstraint isSubtypeOfComponent(const TypeVar &elementVariable, const TypeVar &recordVariable, size_t index)
Constraint on record type and its elements.
bool canBeParsedAsRamUnsigned(const std::string &string)
Can a string be parsed as RamUnsigned.
const TypeSet & getConstantTypes() const
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...
std::vector< Argument * > getArguments() const
Get arguments.
static TypeConstraint subtypesOfTheSameBaseType(const TypeVar &left, const TypeVar &right)
Ensure that types of left and right have the same base types.
bool isAll() const
Universality check.
std::set< const Atom * > sinks
const TypeSet & getConstantNumericTypes() const
TypeAttribute getFunctorArgType(const Functor *functor, const size_t idx) const
TypeSet filter(TypeSet whenAll, F &&f) const
IntrinsicFunctors functorBuiltIn(FunctorOp op)
l j a showGridBackground &&c b raw series this eventEmitter b
Argument * getValue() const
Return value.
void visitNegation(const Negation &cur) override
bool canBeParsedAsRamSigned(const std::string &string)
Can a string be parsed as RamSigned.
void visitNumericConstant(const NumericConstant &constant) override
const std::map< const NumericConstant *, NumericConstant::Type > & getNumericConstantTypes() const
const SumTypeBranchesAnalysis & sumTypesBranches
void collectConstraints(const Clause &clause) override
Visitors.
void visitBranchInit(const BranchInit &adt) override
Initialization of ADT instance.
const Relation * getAtomRelation(const Atom *atom, const Program *program)
Returns the relation referenced by the given atom.
void visitAggregator(const Aggregator &agg) override
bool isInfixFunctorOp(std::string_view symbol)
Determines whether a functor should be written using infix notation (e.g.
void iterateOverAtom(const Atom &atom, std::function< void(const Argument &, const Type &)> map)
Utility function.
void rel(size_t limit, bool showLimit=true)
const Type * getType(const std::string &branch) const
A type can be nullptr in case of a malformed program.
void visitRecordInit(const RecordInit &record) override
ConstraintAnalysisVar< type_lattice > TypeVar
The definition of the type of variable to be utilized in the type analysis.
void visitAtom(const Atom &atom) override