1951 lines
56 KiB
C++
1951 lines
56 KiB
C++
/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
|
|
|
/*
|
|
* Main authors:
|
|
* Guido Tack <guido.tack@monash.edu>
|
|
*/
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef __MINIZINC_AST_HH__
|
|
#define __MINIZINC_AST_HH__
|
|
|
|
#include <minizinc/aststring.hh>
|
|
#include <minizinc/astvec.hh>
|
|
#include <minizinc/gc.hh>
|
|
#include <minizinc/type.hh>
|
|
#include <minizinc/values.hh>
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <iostream>
|
|
#include <limits>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace MiniZinc {
|
|
|
|
class IntLit;
|
|
class FloatLit;
|
|
class SetLit;
|
|
class BoolLit;
|
|
class StringLit;
|
|
class Id;
|
|
class AnonVar;
|
|
class ArrayLit;
|
|
class ArrayAccess;
|
|
class Comprehension;
|
|
class ITE;
|
|
class BinOp;
|
|
class UnOp;
|
|
class Call;
|
|
class VarDecl;
|
|
class Let;
|
|
class TypeInst;
|
|
|
|
class Item;
|
|
class FunctionI;
|
|
|
|
class ExpressionSet;
|
|
class ExpressionSetIter;
|
|
|
|
/// %Location of an expression used during parsing
|
|
class ParserLocation {
|
|
protected:
|
|
/// Source code file name
|
|
ASTString _filename;
|
|
/// Line where expression starts
|
|
unsigned int _first_line;
|
|
/// Line where expression ends
|
|
unsigned int _last_line;
|
|
/// Column where expression starts
|
|
unsigned int _first_column;
|
|
/// Column where expression ends
|
|
unsigned int _last_column;
|
|
|
|
public:
|
|
/// Construct empty location
|
|
ParserLocation(void) : _first_line(1), _last_line(1), _first_column(0), _last_column(0) {}
|
|
|
|
/// Construct location
|
|
ParserLocation(const ASTString& filename, unsigned int first_line, unsigned int first_column,
|
|
unsigned int last_line, unsigned int last_column)
|
|
: _filename(filename),
|
|
_first_line(first_line),
|
|
_last_line(last_line),
|
|
_first_column(first_column),
|
|
_last_column(last_column) {}
|
|
|
|
ASTString filename(void) const { return _filename; }
|
|
void filename(const ASTString& f) { _filename = f; }
|
|
|
|
unsigned int first_line(void) const { return _first_line; }
|
|
void first_line(unsigned int l) { _first_line = l; }
|
|
|
|
unsigned int last_line(void) const { return _last_line; }
|
|
void last_line(unsigned int l) { _last_line = l; }
|
|
|
|
unsigned int first_column(void) const { return _first_column; }
|
|
void first_column(unsigned int c) { _first_column = c; }
|
|
|
|
unsigned int last_column(void) const { return _last_column; }
|
|
void last_column(unsigned int c) { _last_column = c; }
|
|
|
|
std::string toString(void) const {
|
|
std::ostringstream oss;
|
|
oss << _filename << ":" << _first_line << "." << _first_column;
|
|
if (_first_line != _last_line) {
|
|
oss << "-" << _last_line << "." << _last_column;
|
|
} else if (_first_column != _last_column) {
|
|
oss << "-" << _last_column;
|
|
}
|
|
return oss.str();
|
|
}
|
|
};
|
|
|
|
/// %Location of an expression in the source code
|
|
class Location {
|
|
protected:
|
|
/// Internal representation of a Location
|
|
/// Layout depends on sizeof pointer and arguments
|
|
/// 32 bit pointers:
|
|
/// Layout 1: filename (32 bit), first line (8 bit), last line-first line (7 bit), first column
|
|
/// (6 bit), last column (7 bit) Layout 2: filename (32 bit), 4 IntLit for the lines/columns
|
|
/// 64 bit pointers:
|
|
/// Layout 1: filename (64 bit), first line (20 bit), last line-first line (20 bit), first
|
|
/// column (10 bit), last column (10 bit) Layout 2: filename (64 bit), 4 IntLit for the
|
|
/// lines/columns
|
|
class LocVec : public ASTVec {
|
|
protected:
|
|
LocVec(const ASTString& filename, unsigned int first_line, unsigned int first_column,
|
|
unsigned int last_line, unsigned int last_column);
|
|
LocVec(const ASTString& filename, IntVal combined);
|
|
|
|
public:
|
|
static LocVec* a(const ASTString& filename, unsigned int first_line, unsigned int first_column,
|
|
unsigned int last_line, unsigned int last_column);
|
|
void mark(void) {
|
|
_gc_mark = 1;
|
|
if (_data[0]) static_cast<ASTStringO*>(_data[0])->mark();
|
|
}
|
|
|
|
ASTString filename(void) const;
|
|
unsigned int first_line(void) const;
|
|
unsigned int last_line(void) const;
|
|
unsigned int first_column(void) const;
|
|
unsigned int last_column(void) const;
|
|
};
|
|
|
|
union LI {
|
|
LocVec* lv;
|
|
ptrdiff_t t;
|
|
} _loc_info;
|
|
|
|
LocVec* lv(void) const {
|
|
LI li = _loc_info;
|
|
li.t &= ~static_cast<ptrdiff_t>(1);
|
|
return li.lv;
|
|
}
|
|
|
|
public:
|
|
/// Construct empty location
|
|
Location(void) { _loc_info.lv = NULL; }
|
|
|
|
/// Construct location
|
|
Location(const ASTString& filename, unsigned int first_line, unsigned int first_column,
|
|
unsigned int last_line, unsigned int last_column) {
|
|
if (last_line < first_line) throw InternalError("invalid location");
|
|
_loc_info.lv = LocVec::a(filename, first_line, first_column, last_line, last_column);
|
|
}
|
|
|
|
Location(const ParserLocation& loc) {
|
|
_loc_info.lv = LocVec::a(loc.filename(), loc.first_line(), loc.first_column(), loc.last_line(),
|
|
loc.last_column());
|
|
}
|
|
|
|
/// Return string representation
|
|
std::string toString(void) const;
|
|
|
|
/// Return filename
|
|
ASTString filename(void) const { return lv() ? lv()->filename() : ASTString(); }
|
|
|
|
/// Return first line number
|
|
unsigned int first_line(void) const { return lv() ? lv()->first_line() : 0; }
|
|
|
|
/// Return last line number
|
|
unsigned int last_line(void) const { return lv() ? lv()->last_line() : 0; }
|
|
|
|
/// Return first column number
|
|
unsigned int first_column(void) const { return lv() ? lv()->first_column() : 0; }
|
|
|
|
/// Return last column number
|
|
unsigned int last_column(void) const { return lv() ? lv()->last_column() : 0; }
|
|
|
|
/// Return whether location is introduced by the compiler
|
|
bool is_introduced(void) const { return _loc_info.lv == NULL || ((_loc_info.t & 1) != 0); }
|
|
|
|
/// Mark as alive for garbage collection
|
|
void mark(void) const;
|
|
|
|
/// Return location with introduced flag set
|
|
Location introduce(void) const;
|
|
|
|
/// Location used for un-allocated expressions
|
|
static Location nonalloc;
|
|
|
|
ParserLocation parserLocation(void) const {
|
|
return ParserLocation(filename(), first_line(), first_column(), last_line(), last_column());
|
|
}
|
|
};
|
|
|
|
/// Output operator for locations
|
|
template <class Char, class Traits>
|
|
std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os,
|
|
const Location& loc) {
|
|
std::basic_ostringstream<Char, Traits> s;
|
|
s.copyfmt(os);
|
|
s.width(0);
|
|
if (loc.filename() == "") {
|
|
s << "unknown file";
|
|
} else {
|
|
s << loc.filename();
|
|
}
|
|
s << ":" << loc.first_line() << "." << loc.first_column();
|
|
if (loc.first_line() != loc.last_line()) {
|
|
s << "-" << loc.last_line() << "." << loc.last_column();
|
|
} else if (loc.first_column() != loc.last_column()) {
|
|
s << "-" << loc.last_column();
|
|
}
|
|
|
|
return os << s.str();
|
|
}
|
|
|
|
/**
|
|
* \brief Annotations
|
|
*/
|
|
class Annotation {
|
|
private:
|
|
ExpressionSet* _s;
|
|
|
|
/// Delete
|
|
Annotation(const Annotation&);
|
|
/// Delete
|
|
Annotation& operator=(const Annotation&);
|
|
|
|
public:
|
|
Annotation(void) : _s(NULL) {}
|
|
~Annotation(void);
|
|
bool contains(Expression* e) const;
|
|
bool containsCall(const ASTString& id) const;
|
|
bool isEmpty(void) const;
|
|
ExpressionSetIter begin(void) const;
|
|
ExpressionSetIter end(void) const;
|
|
void add(Expression* e);
|
|
void add(std::vector<Expression*> e);
|
|
void remove(Expression* e);
|
|
void removeCall(const ASTString& id);
|
|
void clear(void);
|
|
void merge(const Annotation& ann);
|
|
Call* getCall(const ASTString& id) const;
|
|
|
|
static Annotation empty;
|
|
};
|
|
|
|
/// returns the Annotation specified by the string; returns NULL if not exists
|
|
Expression* getAnnotation(const Annotation& ann, std::string str);
|
|
|
|
/// returns the Annotation specified by the string; returns NULL if not exists
|
|
Expression* getAnnotation(const Annotation& ann, const ASTString& str);
|
|
|
|
/**
|
|
* \brief Base class for expressions
|
|
*/
|
|
class Expression : public ASTNode {
|
|
protected:
|
|
/// The %MiniZinc type of the expression
|
|
Type _type;
|
|
/// The annotations
|
|
Annotation _ann;
|
|
/// The location of the expression
|
|
Location _loc;
|
|
/// The hash value of the expression
|
|
size_t _hash;
|
|
|
|
public:
|
|
/// Identifier of the concrete expression type
|
|
enum ExpressionId {
|
|
E_INTLIT = ASTNode::NID_END + 1,
|
|
E_FLOATLIT,
|
|
E_SETLIT,
|
|
E_BOOLLIT,
|
|
E_STRINGLIT,
|
|
E_ID,
|
|
E_ANON,
|
|
E_ARRAYLIT,
|
|
E_ARRAYACCESS,
|
|
E_COMP,
|
|
E_ITE,
|
|
E_BINOP,
|
|
E_UNOP,
|
|
E_CALL,
|
|
E_VARDECL,
|
|
E_LET,
|
|
E_TI,
|
|
E_TIID,
|
|
EID_END = E_TIID
|
|
};
|
|
|
|
bool isUnboxedVal(void) const {
|
|
if (sizeof(double) <= sizeof(FloatLit*)) {
|
|
// bit 1 or bit 0 is set
|
|
return (reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(3)) != 0;
|
|
} else {
|
|
// bit 0 is set
|
|
return (reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(1)) != 0;
|
|
}
|
|
}
|
|
bool isUnboxedInt(void) const {
|
|
if (sizeof(double) <= sizeof(FloatLit*)) {
|
|
// bit 1 is set, bit 0 is not set
|
|
return (reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(3)) == 2;
|
|
} else {
|
|
// bit 0 is set
|
|
return (reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(1)) == 1;
|
|
}
|
|
}
|
|
bool isUnboxedFloatVal(void) const {
|
|
// bit 0 is set (and doubles fit inside pointers)
|
|
return (sizeof(double) <= sizeof(FloatLit*)) &&
|
|
(reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(1)) == 1;
|
|
}
|
|
|
|
ExpressionId eid(void) const {
|
|
return isUnboxedInt() ? E_INTLIT
|
|
: isUnboxedFloatVal() ? E_FLOATLIT
|
|
: static_cast<ExpressionId>(_id);
|
|
}
|
|
|
|
const Location& loc(void) const { return isUnboxedVal() ? Location::nonalloc : _loc; }
|
|
void loc(const Location& l) {
|
|
if (!isUnboxedVal()) _loc = l;
|
|
}
|
|
const Type& type(void) const {
|
|
return isUnboxedInt() ? Type::unboxedint : isUnboxedFloatVal() ? Type::unboxedfloat : _type;
|
|
}
|
|
void type(const Type& t);
|
|
size_t hash(void) const {
|
|
return isUnboxedInt() ? unboxedIntToIntVal().hash()
|
|
: isUnboxedFloatVal() ? unboxedFloatToFloatVal().hash()
|
|
: _hash;
|
|
}
|
|
|
|
protected:
|
|
/// Combination function for hash values
|
|
void cmb_hash(size_t h) { _hash ^= h + 0x9e3779b9 + (_hash << 6) + (_hash >> 2); }
|
|
/// Combination function for hash values
|
|
size_t cmb_hash(size_t seed, size_t h) {
|
|
seed ^= h + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
|
return seed;
|
|
}
|
|
|
|
/// Compute base hash value
|
|
void init_hash(void) { _hash = cmb_hash(0, _id); }
|
|
|
|
/// Check if \a e0 and \a e1 are equal
|
|
static bool equal_internal(const Expression* e0, const Expression* e1);
|
|
|
|
/// Constructor
|
|
Expression(const Location& loc, const ExpressionId& eid, const Type& t)
|
|
: ASTNode(eid), _type(t), _loc(loc) {}
|
|
|
|
public:
|
|
IntVal unboxedIntToIntVal(void) const {
|
|
assert(isUnboxedInt());
|
|
if (sizeof(double) <= sizeof(FloatVal*)) {
|
|
unsigned long long int i = reinterpret_cast<ptrdiff_t>(this) & ~static_cast<ptrdiff_t>(7);
|
|
bool pos = ((reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(4)) == 0);
|
|
if (pos) {
|
|
return i >> 3;
|
|
} else {
|
|
return -(static_cast<long long int>(i >> 3));
|
|
}
|
|
} else {
|
|
unsigned long long int i = reinterpret_cast<ptrdiff_t>(this) & ~static_cast<ptrdiff_t>(3);
|
|
bool pos = ((reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(2)) == 0);
|
|
if (pos) {
|
|
return i >> 2;
|
|
} else {
|
|
return -(static_cast<long long int>(i >> 2));
|
|
}
|
|
}
|
|
}
|
|
static IntLit* intToUnboxedInt(long long int i) {
|
|
static const unsigned int pointerBits = sizeof(IntLit*) * 8;
|
|
if (sizeof(double) <= sizeof(FloatVal*)) {
|
|
static const long long int maxUnboxedVal =
|
|
(static_cast<long long int>(1) << (pointerBits - 3)) - static_cast<long long int>(1);
|
|
if (i < -maxUnboxedVal || i > maxUnboxedVal) return NULL;
|
|
long long int j = i < 0 ? -i : i;
|
|
ptrdiff_t ubi_p = (static_cast<ptrdiff_t>(j) << 3) | static_cast<ptrdiff_t>(2);
|
|
if (i < 0) ubi_p = ubi_p | static_cast<ptrdiff_t>(4);
|
|
return reinterpret_cast<IntLit*>(ubi_p);
|
|
} else {
|
|
static const long long int maxUnboxedVal =
|
|
(static_cast<long long int>(1) << (pointerBits - 2)) - static_cast<long long int>(1);
|
|
if (i < -maxUnboxedVal || i > maxUnboxedVal) return NULL;
|
|
long long int j = i < 0 ? -i : i;
|
|
ptrdiff_t ubi_p = (static_cast<ptrdiff_t>(j) << 2) | static_cast<ptrdiff_t>(1);
|
|
if (i < 0) ubi_p = ubi_p | static_cast<ptrdiff_t>(2);
|
|
return reinterpret_cast<IntLit*>(ubi_p);
|
|
}
|
|
}
|
|
FloatVal unboxedFloatToFloatVal(void) const {
|
|
assert(isUnboxedFloatVal());
|
|
union {
|
|
double d;
|
|
uint64_t bits;
|
|
const Expression* p;
|
|
} _u;
|
|
_u.p = this;
|
|
_u.bits = _u.bits >> 1;
|
|
uint64_t exponent = (_u.bits & (static_cast<uint64_t>(0x3FF) << 52)) >> 52;
|
|
if (exponent != 0) {
|
|
exponent += 512; // reconstruct original bias of 1023
|
|
}
|
|
uint64_t sign = (_u.bits & (static_cast<uint64_t>(1) << 62) ? 1 : 0);
|
|
_u.bits = (sign << 63) | (exponent << 52) | (_u.bits & static_cast<uint64_t>(0xFFFFFFFFFFFFF));
|
|
return _u.d;
|
|
}
|
|
static FloatLit* doubleToUnboxedFloatVal(double d) {
|
|
if (sizeof(double) > sizeof(FloatLit*)) return NULL;
|
|
union {
|
|
double d;
|
|
uint64_t bits;
|
|
FloatLit* p;
|
|
} _u;
|
|
_u.d = d;
|
|
|
|
uint64_t exponent = (_u.bits & (static_cast<uint64_t>(0x7FF) << 52)) >> 52;
|
|
if (exponent != 0) {
|
|
if (exponent < 513 || exponent > 1534) return NULL; // exponent doesn't fit in 10 bits
|
|
exponent -= 512; // make exponent fit in 10 bits, with bias 511
|
|
}
|
|
bool sign = (_u.bits & (static_cast<uint64_t>(1) << 63)) != 0;
|
|
|
|
_u.bits = _u.bits &
|
|
~(static_cast<uint64_t>(0x7FF) << 52); // mask out top 11 bits (previously exponent)
|
|
_u.bits = (_u.bits << 1) | 1u; // shift by one bit and add tag for double
|
|
_u.bits =
|
|
_u.bits | (static_cast<uint64_t>(sign) << 63) | (static_cast<uint64_t>(exponent) << 53);
|
|
return _u.p;
|
|
}
|
|
|
|
bool isTagged(void) const {
|
|
// only bit 2 is set
|
|
if (isUnboxedVal()) return false;
|
|
if (sizeof(double) <= sizeof(FloatVal*))
|
|
return (reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(7)) == 4;
|
|
else
|
|
return (reinterpret_cast<ptrdiff_t>(this) & static_cast<ptrdiff_t>(3)) == 2;
|
|
}
|
|
|
|
Expression* tag(void) const {
|
|
assert(!isUnboxedVal());
|
|
if (sizeof(double) <= sizeof(FloatVal*))
|
|
return reinterpret_cast<Expression*>(reinterpret_cast<ptrdiff_t>(this) |
|
|
static_cast<ptrdiff_t>(4));
|
|
else
|
|
return reinterpret_cast<Expression*>(reinterpret_cast<ptrdiff_t>(this) |
|
|
static_cast<ptrdiff_t>(2));
|
|
}
|
|
Expression* untag(void) {
|
|
if (isUnboxedVal()) return this;
|
|
if (sizeof(double) <= sizeof(FloatVal*))
|
|
return reinterpret_cast<Expression*>(reinterpret_cast<ptrdiff_t>(this) &
|
|
~static_cast<ptrdiff_t>(4));
|
|
else
|
|
return reinterpret_cast<Expression*>(reinterpret_cast<ptrdiff_t>(this) &
|
|
~static_cast<ptrdiff_t>(2));
|
|
}
|
|
|
|
/// Test if expression is of type \a T
|
|
template <class T>
|
|
bool isa(void) const {
|
|
#ifdef __clang__
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wtautological-undefined-compare"
|
|
#endif
|
|
if (nullptr == this) throw InternalError("isa: nullptr");
|
|
#ifdef __clang__
|
|
#pragma clang diagnostic pop
|
|
#endif
|
|
return isUnboxedInt() ? T::eid == E_INTLIT
|
|
: isUnboxedFloatVal() ? T::eid == E_FLOATLIT
|
|
: _id == T::eid;
|
|
}
|
|
/// Cast expression to type \a T*
|
|
template <class T>
|
|
T* cast(void) {
|
|
assert(isa<T>());
|
|
return static_cast<T*>(this);
|
|
}
|
|
/// Cast expression to type \a const T*
|
|
template <class T>
|
|
const T* cast(void) const {
|
|
assert(isa<T>());
|
|
return static_cast<const T*>(this);
|
|
}
|
|
/// Cast expression to type \a T* or NULL if types do not match
|
|
template <class T>
|
|
T* dyn_cast(void) {
|
|
return isa<T>() ? static_cast<T*>(this) : NULL;
|
|
}
|
|
/// Cast expression to type \a const T* or NULL if types do not match
|
|
template <class T>
|
|
const T* dyn_cast(void) const {
|
|
return isa<T>() ? static_cast<const T*>(this) : NULL;
|
|
}
|
|
|
|
/// Cast expression to type \a T*
|
|
template <class T>
|
|
static T* cast(Expression* e) {
|
|
return e == NULL ? NULL : e->cast<T>();
|
|
}
|
|
/// Cast expression to type \a const T*
|
|
template <class T>
|
|
static const T* cast(const Expression* e) {
|
|
return e == NULL ? NULL : e->cast<T>();
|
|
}
|
|
/// Cast expression to type \a T* or NULL if types do not match
|
|
template <class T>
|
|
static T* dyn_cast(Expression* e) {
|
|
return e == NULL ? NULL : e->dyn_cast<T>();
|
|
}
|
|
/// Cast expression to type \a const T* or NULL if types do not match
|
|
template <class T>
|
|
static const T* dyn_cast(const Expression* e) {
|
|
return e == NULL ? NULL : e->dyn_cast<T>();
|
|
}
|
|
|
|
/// Add annotation \a ann to the expression
|
|
void addAnnotation(Expression* ann);
|
|
|
|
/// Add annotation \a ann to the expression
|
|
void addAnnotations(std::vector<Expression*> ann);
|
|
|
|
const Annotation& ann(void) const { return isUnboxedVal() ? Annotation::empty : _ann; }
|
|
Annotation& ann(void) { return isUnboxedVal() ? Annotation::empty : _ann; }
|
|
|
|
/// Return hash value of \a e
|
|
static size_t hash(const Expression* e) { return e == NULL ? 0 : e->hash(); }
|
|
|
|
/// Check if \a e0 and \a e1 are equal
|
|
static bool equal(const Expression* e0, const Expression* e1);
|
|
|
|
/// Mark \a e as alive for garbage collection
|
|
static void mark(Expression* e);
|
|
};
|
|
|
|
/// \brief Integer literal expression
|
|
class IntLit : public Expression {
|
|
protected:
|
|
/// The value of this expression
|
|
IntVal _v;
|
|
/// Constructor
|
|
IntLit(const Location& loc, IntVal v);
|
|
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_INTLIT;
|
|
/// Access value
|
|
IntVal v(void) const { return isUnboxedInt() ? unboxedIntToIntVal() : _v; }
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
/// Allocate literal
|
|
static IntLit* a(IntVal v);
|
|
/// Allocate literal for enumerated type (only used internally for generators)
|
|
static IntLit* aEnum(IntVal v, unsigned int enumId);
|
|
};
|
|
/// \brief Float literal expression
|
|
class FloatLit : public Expression {
|
|
protected:
|
|
/// The value of this expression
|
|
FloatVal _v;
|
|
/// Constructor
|
|
FloatLit(const Location& loc, FloatVal v);
|
|
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_FLOATLIT;
|
|
/// Access value
|
|
FloatVal v(void) const { return isUnboxedFloatVal() ? unboxedFloatToFloatVal() : _v; }
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
/// Allocate literal
|
|
static FloatLit* a(FloatVal v);
|
|
};
|
|
/// \brief Set literal expression
|
|
class SetLit : public Expression {
|
|
protected:
|
|
/// The value of this expression
|
|
ASTExprVec<Expression> _v;
|
|
union {
|
|
/// A range-list based representation for an integer set, or NULL
|
|
IntSetVal* isv;
|
|
/// A range-list based representation for an float set, or NULL
|
|
FloatSetVal* fsv;
|
|
} _u;
|
|
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_SETLIT;
|
|
/// Construct set \$f\{v1,\dots,vn\}\$f
|
|
SetLit(const Location& loc, const std::vector<Expression*>& v);
|
|
/// Construct set \$f\{v1,\dots,vn\}\$f
|
|
SetLit(const Location& loc, ASTExprVec<Expression> v);
|
|
/// Construct set
|
|
SetLit(const Location& loc, IntSetVal* isv);
|
|
/// Construct set
|
|
SetLit(const Location& loc, FloatSetVal* fsv);
|
|
/// Access value
|
|
ASTExprVec<Expression> v(void) const { return _v; }
|
|
/// Set value
|
|
void v(const ASTExprVec<Expression>& val) { _v = val; }
|
|
/// Access integer set value if present
|
|
IntSetVal* isv(void) const { return type().bt() == Type::BT_INT ? _u.isv : NULL; }
|
|
/// Set integer set value
|
|
void isv(IntSetVal* val) { _u.isv = val; }
|
|
/// Access float set value if present
|
|
FloatSetVal* fsv(void) const { return type().bt() == Type::BT_FLOAT ? _u.fsv : NULL; }
|
|
/// Set integer set value
|
|
void fsv(FloatSetVal* val) { _u.fsv = val; }
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
};
|
|
/// \brief Boolean literal expression
|
|
class BoolLit : public Expression {
|
|
protected:
|
|
/// The value of this expression
|
|
bool _v;
|
|
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_BOOLLIT;
|
|
/// Constructor
|
|
BoolLit(const Location& loc, bool v);
|
|
/// Access value
|
|
bool v(void) const { return _v; }
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
};
|
|
/// \brief String literal expression
|
|
class StringLit : public Expression {
|
|
protected:
|
|
/// The value of this expression
|
|
ASTString _v;
|
|
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_STRINGLIT;
|
|
/// Constructor
|
|
StringLit(const Location& loc, const std::string& v);
|
|
/// Constructor
|
|
StringLit(const Location& loc, const ASTString& v);
|
|
/// Access value
|
|
ASTString v(void) const { return _v; }
|
|
/// Set value
|
|
void v(const ASTString& val) { _v = val; }
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
};
|
|
/// \brief Identifier expression
|
|
class Id : public Expression {
|
|
protected:
|
|
/// The string identifier
|
|
void* _v_or_idn;
|
|
/// The declaration corresponding to this identifier (may be NULL)
|
|
Expression* _decl;
|
|
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_ID;
|
|
/// Constructor (\a decl may be NULL)
|
|
Id(const Location& loc, const std::string& v, VarDecl* decl);
|
|
/// Constructor (\a decl may be NULL)
|
|
Id(const Location& loc, const ASTString& v, VarDecl* decl);
|
|
/// Constructor (\a decl may be NULL)
|
|
Id(const Location& loc, long long int idn, VarDecl* decl);
|
|
/// Access identifier
|
|
ASTString v(void) const;
|
|
/// Set identifier
|
|
void v(const ASTString& val) { _v_or_idn = val.aststr(); }
|
|
/// Access identifier number
|
|
long long int idn(void) const;
|
|
/// Set identifier number
|
|
void idn(long long int n) {
|
|
_v_or_idn =
|
|
reinterpret_cast<void*>((static_cast<ptrdiff_t>(n) << 1) | static_cast<ptrdiff_t>(1));
|
|
rehash();
|
|
}
|
|
/// Return identifier or X_INTRODUCED plus identifier number
|
|
ASTString str(void) const;
|
|
/// Access declaration
|
|
VarDecl* decl(void) const {
|
|
Expression* d = _decl;
|
|
while (d && d->isa<Id>()) d = d->cast<Id>()->_decl;
|
|
return Expression::cast<VarDecl>(d);
|
|
}
|
|
/// Set declaration
|
|
void decl(VarDecl* d);
|
|
/// Redirect to another Id \a id
|
|
void redirect(Id* id) {
|
|
assert(_decl == NULL || _decl->isa<VarDecl>());
|
|
_decl = id;
|
|
}
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
};
|
|
/// \brief Type-inst identifier expression
|
|
class TIId : public Expression {
|
|
protected:
|
|
/// The string identifier
|
|
ASTString _v;
|
|
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_TIID;
|
|
/// Constructor
|
|
TIId(const Location& loc, const std::string& v);
|
|
/// Access identifier
|
|
ASTString v(void) const { return _v; }
|
|
/// Set identifier
|
|
void v(const ASTString& val) { _v = val; }
|
|
/// Check whether it is an enum identifier (starting with two $ signs)
|
|
bool isEnum(void) const { return _v.c_str()[0] == '$'; }
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
};
|
|
/// \brief Anonymous variable expression
|
|
class AnonVar : public Expression {
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_ANON;
|
|
/// Constructor
|
|
AnonVar(const Location& loc);
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
};
|
|
/// \brief Array literal expression
|
|
class ArrayLit : public Expression {
|
|
friend class Expression;
|
|
|
|
protected:
|
|
/// The array
|
|
union {
|
|
/// An expression vector (if _flag_2==false)
|
|
ASTExprVecO<Expression*>* _v;
|
|
/// Another array literal (if _flag_2==true)
|
|
ArrayLit* _al;
|
|
} _u;
|
|
/// The declared array dimensions
|
|
// If _flag_2 is true, then this is an array view. In that case,
|
|
// the _dims array holds the sliced dimensions
|
|
ASTIntVec _dims;
|
|
/// Set compressed vector (initial repetitions are removed)
|
|
void compress(const std::vector<Expression*>& v, const std::vector<int>& dims);
|
|
|
|
public:
|
|
/// Index conversion from slice to original
|
|
int origIdx(int i) const;
|
|
/// Get element \a i of a sliced array
|
|
Expression* slice_get(int i) const;
|
|
/// Set element \a i of a sliced array
|
|
void slice_set(int i, Expression* e);
|
|
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_ARRAYLIT;
|
|
/// Constructor
|
|
ArrayLit(const Location& loc, const std::vector<Expression*>& v,
|
|
const std::vector<std::pair<int, int> >& dims);
|
|
/// Constructor (existing content)
|
|
ArrayLit(const Location& loc, ArrayLit& v, const std::vector<std::pair<int, int> >& dims);
|
|
/// Constructor (one-dimensional, existing content)
|
|
ArrayLit(const Location& loc, ArrayLit& v);
|
|
/// Constructor (one-dimensional)
|
|
ArrayLit(const Location& loc, const std::vector<Expression*>& v);
|
|
/// Constructor (two-dimensional)
|
|
ArrayLit(const Location& loc, const std::vector<std::vector<Expression*> >& v);
|
|
/// Constructor for slices
|
|
ArrayLit(const Location& loc, ArrayLit* v, const std::vector<std::pair<int, int> >& dims,
|
|
const std::vector<std::pair<int, int> >& slice);
|
|
/// Constructor (one-dimensional)
|
|
ArrayLit(const Location& loc, const std::vector<KeepAlive>& v);
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
|
|
// The following methods are only used for copying
|
|
|
|
/// Access value
|
|
ASTExprVec<Expression> getVec(void) const {
|
|
assert(!_flag_2);
|
|
return _u._v;
|
|
}
|
|
/// Set value
|
|
void setVec(const ASTExprVec<Expression>& val) {
|
|
assert(!_flag_2);
|
|
_u._v = val.vec();
|
|
}
|
|
/// Get underlying array (if this is an array slice) or NULL
|
|
ArrayLit* getSliceLiteral(void) const { return _flag_2 ? _u._al : NULL; }
|
|
/// Get underlying _dims vector
|
|
ASTIntVec dimsInternal(void) const { return _dims; }
|
|
|
|
/// Return number of dimensions
|
|
int dims(void) const;
|
|
/// Return minimum index of dimension \a i
|
|
int min(int i) const;
|
|
/// Return maximum index of dimension \a i
|
|
int max(int i) const;
|
|
/// Return the length of the array
|
|
int length(void) const;
|
|
/// Turn into 1d array (only used at the end of flattening)
|
|
void make1d(void);
|
|
/// Check if this array was produced by flattening
|
|
bool flat(void) const { return _flag_1; }
|
|
/// Set whether this array was produced by flattening
|
|
void flat(bool b) { _flag_1 = b; }
|
|
/// Return size of underlying array
|
|
unsigned int size(void) const { return (_flag_2 || _u._v->flag()) ? length() : _u._v->size(); }
|
|
/// Access element \a i
|
|
Expression* operator[](int i) const {
|
|
return (_flag_2 || _u._v->flag()) ? slice_get(i) : (*_u._v)[i];
|
|
}
|
|
/// Set element \a i
|
|
void set(int i, Expression* e) {
|
|
if (_flag_2 || _u._v->flag()) {
|
|
slice_set(i, e);
|
|
} else {
|
|
(*_u._v)[i] = e;
|
|
}
|
|
}
|
|
};
|
|
/// \brief Array access expression
|
|
class ArrayAccess : public Expression {
|
|
protected:
|
|
/// The array to access
|
|
Expression* _v;
|
|
/// The indexes (for all array dimensions)
|
|
ASTExprVec<Expression> _idx;
|
|
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_ARRAYACCESS;
|
|
/// Constructor
|
|
ArrayAccess(const Location& loc, Expression* v, const std::vector<Expression*>& idx);
|
|
/// Constructor
|
|
ArrayAccess(const Location& loc, Expression* v, ASTExprVec<Expression> idx);
|
|
/// Access value
|
|
Expression* v(void) const { return _v; }
|
|
/// Set value
|
|
void v(Expression* val) { _v = val; }
|
|
/// Access index sets
|
|
ASTExprVec<Expression> idx(void) const { return _idx; }
|
|
/// Set index sets
|
|
void idx(const ASTExprVec<Expression>& idx) { _idx = idx; }
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
};
|
|
/**
|
|
* \brief Generators for comprehensions
|
|
*
|
|
* A generator consists of a list of variable declarations, one for
|
|
* each generated variable, and the expression to generate. E.g.,
|
|
* the Zinc expression [ x[i,j,k] | i,j in 1..10, k in 1..5] contains
|
|
* two generators. The first one has variable declarations for i and j
|
|
* and the expression 1..10, and the second one has a variable declaration
|
|
* for k and the expression 1..5.
|
|
*
|
|
*/
|
|
class Generator {
|
|
friend class Comprehension;
|
|
|
|
protected:
|
|
/// Variable declarations
|
|
std::vector<VarDecl*> _v;
|
|
/// in-expression
|
|
Expression* _in;
|
|
/// where-expression
|
|
Expression* _where;
|
|
|
|
public:
|
|
/// Allocate
|
|
Generator(const std::vector<std::string>& v, Expression* in, Expression* where);
|
|
/// Allocate
|
|
Generator(const std::vector<ASTString>& v, Expression* in, Expression* where);
|
|
/// Allocate
|
|
Generator(const std::vector<Id*>& v, Expression* in, Expression* where);
|
|
/// Allocate
|
|
Generator(const std::vector<VarDecl*>& v, Expression* in, Expression* where);
|
|
/// Allocate single where clause (without generator) at position \a pos
|
|
Generator(int pos, Expression* where);
|
|
};
|
|
/// \brief A list of generators with one where-expression
|
|
struct Generators {
|
|
/// %Generators
|
|
std::vector<Generator> _g;
|
|
/// Constructor
|
|
Generators(void) {}
|
|
};
|
|
/// \brief An expression representing an array- or set-comprehension
|
|
class Comprehension : public Expression {
|
|
friend class Expression;
|
|
|
|
protected:
|
|
/// The expression to generate
|
|
Expression* _e;
|
|
/// A list of generator expressions
|
|
ASTExprVec<Expression> _g;
|
|
/// A list of indices where generators start
|
|
ASTIntVec _g_idx;
|
|
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_COMP;
|
|
/// Constructor
|
|
Comprehension(const Location& loc, Expression* e, Generators& g, bool set);
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
/// Whether comprehension is a set
|
|
bool set(void) const;
|
|
|
|
/// Return number of generators
|
|
int n_generators(void) const;
|
|
/// Return "in" expression for generator \a i
|
|
Expression* in(int i);
|
|
/// Return "in" expression for generator \a i
|
|
const Expression* in(int i) const;
|
|
/// Return number of declarations for generator \a i
|
|
int n_decls(int i) const;
|
|
/// Return declaration \a i for generator \a gen
|
|
VarDecl* decl(int gen, int i);
|
|
/// Return declaration \a i for generator \a gen
|
|
const VarDecl* decl(int gen, int i) const;
|
|
/// Return where clause for generator \a i
|
|
Expression* where(int i);
|
|
/// Return where clause for generator \a i
|
|
const Expression* where(int i) const;
|
|
/// Return generator body
|
|
Expression* e(void) const { return _e; }
|
|
/// Set generator body
|
|
void e(Expression* e0) { _e = e0; }
|
|
/// Re-construct (used for copying)
|
|
void init(Expression* e, Generators& g);
|
|
};
|
|
/// \brief If-then-else expression
|
|
class ITE : public Expression {
|
|
friend class Expression;
|
|
|
|
protected:
|
|
/// List of if-then-pairs
|
|
ASTExprVec<Expression> _e_if_then;
|
|
/// Else-expression
|
|
Expression* _e_else;
|
|
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_ITE;
|
|
/// Constructor
|
|
ITE(const Location& loc, const std::vector<Expression*>& e_if_then, Expression* e_else);
|
|
int size(void) const { return _e_if_then.size() / 2; }
|
|
Expression* e_if(int i) { return _e_if_then[2 * i]; }
|
|
Expression* e_then(int i) { return _e_if_then[2 * i + 1]; }
|
|
Expression* e_else(void) { return _e_else; }
|
|
const Expression* e_if(int i) const { return _e_if_then[2 * i]; }
|
|
const Expression* e_then(int i) const { return _e_if_then[2 * i + 1]; }
|
|
const Expression* e_else(void) const { return _e_else; }
|
|
void e_then(int i, Expression* e) { _e_if_then[2 * i + 1] = e; }
|
|
void e_else(Expression* e) { _e_else = e; }
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
/// Re-construct (used for copying)
|
|
void init(const std::vector<Expression*>& e_if_then, Expression* e_else);
|
|
};
|
|
|
|
/// Type of binary operators
|
|
enum BinOpType {
|
|
BOT_PLUS,
|
|
BOT_MINUS,
|
|
BOT_MULT,
|
|
BOT_DIV,
|
|
BOT_IDIV,
|
|
BOT_MOD,
|
|
BOT_POW,
|
|
BOT_LE,
|
|
BOT_LQ,
|
|
BOT_GR,
|
|
BOT_GQ,
|
|
BOT_EQ,
|
|
BOT_NQ,
|
|
BOT_IN,
|
|
BOT_SUBSET,
|
|
BOT_SUPERSET,
|
|
BOT_UNION,
|
|
BOT_DIFF,
|
|
BOT_SYMDIFF,
|
|
BOT_INTERSECT,
|
|
BOT_PLUSPLUS,
|
|
BOT_EQUIV,
|
|
BOT_IMPL,
|
|
BOT_RIMPL,
|
|
BOT_OR,
|
|
BOT_AND,
|
|
BOT_XOR,
|
|
BOT_DOTDOT
|
|
};
|
|
/// \brief Binary-operator expression
|
|
class BinOp : public Expression {
|
|
protected:
|
|
/// Left hand side expression
|
|
Expression* _e0;
|
|
/// Right hand side expression
|
|
Expression* _e1;
|
|
/// The predicate or function declaration (or NULL)
|
|
FunctionI* _decl;
|
|
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_BINOP;
|
|
/// Constructor
|
|
BinOp(const Location& loc, Expression* e0, BinOpType op, Expression* e1);
|
|
/// Access left hand side
|
|
Expression* lhs(void) const { return _e0; }
|
|
/// Set left hand side
|
|
void lhs(Expression* e) { _e0 = e; }
|
|
/// Access right hand side
|
|
Expression* rhs(void) const { return _e1; }
|
|
/// Set right hand side
|
|
void rhs(Expression* e) { _e1 = e; }
|
|
/// Access argument \a i
|
|
Expression* arg(int i) {
|
|
assert(i == 0 || i == 1);
|
|
return i == 0 ? _e0 : _e1;
|
|
}
|
|
/// Return number of arguments
|
|
unsigned int n_args(void) const { return 2; }
|
|
/// Access declaration
|
|
FunctionI* decl(void) const { return _decl; }
|
|
/// Set declaration
|
|
void decl(FunctionI* f) { _decl = f; }
|
|
/// Return string representation of the operator
|
|
ASTString opToString(void) const;
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
/// Return operator type
|
|
BinOpType op(void) const;
|
|
};
|
|
|
|
/// Type of unary operators
|
|
enum UnOpType { UOT_NOT, UOT_PLUS, UOT_MINUS };
|
|
/// \brief Unary-operator expressions
|
|
class UnOp : public Expression {
|
|
protected:
|
|
/// %Expression
|
|
Expression* _e0;
|
|
/// The predicate or function declaration (or NULL)
|
|
FunctionI* _decl;
|
|
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_UNOP;
|
|
/// Constructor
|
|
UnOp(const Location& loc, UnOpType op, Expression* e);
|
|
/// Access expression
|
|
Expression* e(void) const { return _e0; }
|
|
/// Set expression
|
|
void e(Expression* e0) { _e0 = e0; }
|
|
/// Access argument \a i
|
|
Expression* arg(int i) {
|
|
assert(i == 0);
|
|
return _e0;
|
|
}
|
|
/// Return number of arguments
|
|
unsigned int n_args(void) const { return 1; }
|
|
/// Access declaration
|
|
FunctionI* decl(void) const { return _decl; }
|
|
/// Set declaration
|
|
void decl(FunctionI* f) { _decl = f; }
|
|
ASTString opToString(void) const;
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
/// Return operator type
|
|
UnOpType op(void) const;
|
|
};
|
|
|
|
/// \brief A predicate or function call expression
|
|
class Call : public Expression {
|
|
friend class Expression;
|
|
|
|
protected:
|
|
union {
|
|
/// Identifier of called predicate or function
|
|
ASTStringO* _id;
|
|
/// The predicate or function declaration (or NULL)
|
|
FunctionI* _decl;
|
|
} _u_id;
|
|
union {
|
|
/// Single-argument call (tagged pointer)
|
|
Expression* _oneArg;
|
|
/// Arguments to the call
|
|
ASTExprVecO<Expression*>* _args;
|
|
} _u;
|
|
/// Check if _u_id contains an id or a decl
|
|
bool hasId(void) const;
|
|
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_CALL;
|
|
/// Constructor
|
|
Call(const Location& loc, const std::string& id, const std::vector<Expression*>& args);
|
|
/// Constructor
|
|
Call(const Location& loc, const ASTString& id, const std::vector<Expression*>& args);
|
|
/// Access identifier
|
|
ASTString id(void) const;
|
|
/// Set identifier (overwrites decl)
|
|
void id(const ASTString& i);
|
|
/// Number of arguments
|
|
unsigned int n_args(void) const {
|
|
return _u._oneArg->isUnboxedVal() || _u._oneArg->isTagged() ? 1 : _u._args->size();
|
|
}
|
|
/// Access argument \a i
|
|
Expression* arg(int i) const {
|
|
assert(i < n_args());
|
|
if (_u._oneArg->isUnboxedVal() || _u._oneArg->isTagged()) {
|
|
assert(i == 0);
|
|
return _u._oneArg->isUnboxedVal() ? _u._oneArg : _u._oneArg->untag();
|
|
} else {
|
|
return (*_u._args)[i];
|
|
}
|
|
}
|
|
/// Set argument \a i
|
|
void arg(int i, Expression* e) {
|
|
assert(i < n_args());
|
|
if (_u._oneArg->isUnboxedVal() || _u._oneArg->isTagged()) {
|
|
assert(i == 0);
|
|
_u._oneArg = e->isUnboxedVal() ? e : e->tag();
|
|
} else {
|
|
(*_u._args)[i] = e;
|
|
}
|
|
}
|
|
/// Set arguments
|
|
void args(const ASTExprVec<Expression>& a) {
|
|
if (a.size() == 1) {
|
|
_u._oneArg = a[0]->isUnboxedVal() ? a[0] : a[0]->tag();
|
|
} else {
|
|
_u._args = a.vec();
|
|
assert(!_u._oneArg->isTagged());
|
|
}
|
|
}
|
|
/// Access declaration
|
|
FunctionI* decl(void) const;
|
|
/// Set declaration (overwrites id)
|
|
void decl(FunctionI* f);
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
};
|
|
/// \brief A variable declaration expression
|
|
class VarDecl : public Expression {
|
|
protected:
|
|
/// Type-inst of the declared variable
|
|
TypeInst* _ti;
|
|
/// Identifier
|
|
Id* _id;
|
|
/// Initialisation expression (can be NULL)
|
|
Expression* _e;
|
|
/// Flattened version of the VarDecl
|
|
WeakRef _flat;
|
|
/// Integer payload
|
|
int _payload;
|
|
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_VARDECL;
|
|
/// Constructor
|
|
VarDecl(const Location& loc, TypeInst* ti, const std::string& id, Expression* e = NULL);
|
|
/// Constructor
|
|
VarDecl(const Location& loc, TypeInst* ti, const ASTString& id, Expression* e = NULL);
|
|
// Constructor
|
|
VarDecl(const Location& loc, TypeInst* ti, long long int idn, Expression* e = NULL);
|
|
/// Constructor
|
|
VarDecl(const Location& loc, TypeInst* ti, Id* id, Expression* e = NULL);
|
|
|
|
/// Access TypeInst
|
|
TypeInst* ti(void) const { return _ti; }
|
|
/// Set TypeInst
|
|
void ti(TypeInst* t) { _ti = t; }
|
|
/// Access identifier
|
|
Id* id(void) const { return _id; }
|
|
/// Access initialisation expression
|
|
Expression* e(void) const;
|
|
/// Set initialisation expression
|
|
void e(Expression* rhs);
|
|
/// Access flattened version
|
|
VarDecl* flat(void) { return _flat() ? _flat()->cast<VarDecl>() : NULL; }
|
|
/// Set flattened version
|
|
void flat(VarDecl* vd);
|
|
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
/// Whether variable is toplevel
|
|
bool toplevel(void) const;
|
|
/// Whether variable is toplevel
|
|
void toplevel(bool t);
|
|
/// Whether variable is introduced
|
|
bool introduced(void) const;
|
|
/// Whether variable is introduced
|
|
void introduced(bool t);
|
|
/// Whether variable has been evaluated
|
|
bool evaluated(void) const;
|
|
/// Whether variable has been evaluated
|
|
void evaluated(bool t);
|
|
/// Access payload
|
|
int payload(void) const { return _payload; }
|
|
/// Set payload
|
|
void payload(int i) { _payload = i; }
|
|
/// Put current value on trail
|
|
void trail(void);
|
|
};
|
|
|
|
class EnvI;
|
|
class CopyMap;
|
|
|
|
/// \brief %Let expression
|
|
class Let : public Expression {
|
|
friend Expression* copy(EnvI& env, CopyMap& m, Expression* e, bool followIds, bool copyFundecls,
|
|
bool isFlatModel);
|
|
friend class Expression;
|
|
|
|
protected:
|
|
/// List of local declarations
|
|
ASTExprVec<Expression> _let;
|
|
/// Copy of original local declarations
|
|
ASTExprVec<Expression> _let_orig;
|
|
/// Body of the let
|
|
Expression* _in;
|
|
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_LET;
|
|
/// Constructor
|
|
Let(const Location& loc, const std::vector<Expression*>& let, Expression* in);
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
|
|
/// Access local declarations
|
|
ASTExprVec<Expression> let(void) const { return _let; }
|
|
/// Access local declarations
|
|
ASTExprVec<Expression> let_orig(void) const { return _let_orig; }
|
|
/// Access body
|
|
Expression* in(void) const { return _in; }
|
|
|
|
/// Remember current let bindings
|
|
void pushbindings(void);
|
|
/// Restore previous let bindings
|
|
void popbindings(void);
|
|
};
|
|
|
|
/// \brief Type-inst expression
|
|
class TypeInst : public Expression {
|
|
protected:
|
|
/// Ranges of an array expression
|
|
ASTExprVec<TypeInst> _ranges;
|
|
/// Declared domain (or NULL)
|
|
Expression* _domain;
|
|
|
|
public:
|
|
/// The identifier of this expression type
|
|
static const ExpressionId eid = E_TI;
|
|
/// Constructor
|
|
TypeInst(const Location& loc, const Type& t, ASTExprVec<TypeInst> ranges,
|
|
Expression* domain = NULL);
|
|
/// Constructor
|
|
TypeInst(const Location& loc, const Type& t, Expression* domain = NULL);
|
|
|
|
/// Access ranges
|
|
ASTExprVec<TypeInst> ranges(void) const { return _ranges; }
|
|
/// Access domain
|
|
Expression* domain(void) const { return _domain; }
|
|
//// Set domain
|
|
void domain(Expression* d) { _domain = d; }
|
|
|
|
/// Set ranges to \a ranges
|
|
void setRanges(const std::vector<TypeInst*>& ranges);
|
|
bool isarray(void) const { return _ranges.size() > 0; }
|
|
bool hasTiVariable(void) const;
|
|
/// Recompute hash value
|
|
void rehash(void);
|
|
/// Check if domain is computed from right hand side of variable
|
|
bool computedDomain(void) const { return _flag_1; }
|
|
/// Set if domain is computed from right hand side of variable
|
|
void setComputedDomain(bool b) { _flag_1 = b; }
|
|
/// Check if this TypeInst represents an enum
|
|
bool isEnum(void) const { return _flag_2; }
|
|
/// Set if this TypeInst represents an enum
|
|
void setIsEnum(bool b) { _flag_2 = b; }
|
|
};
|
|
|
|
/**
|
|
* \brief Base-class for items
|
|
*/
|
|
class Item : public ASTNode {
|
|
protected:
|
|
/// Location of the item
|
|
Location _loc;
|
|
|
|
public:
|
|
/// Identifier of the concrete item type
|
|
enum ItemId {
|
|
II_INC = Expression::EID_END + 1,
|
|
II_VD,
|
|
II_ASN,
|
|
II_CON,
|
|
II_SOL,
|
|
II_OUT,
|
|
II_FUN,
|
|
II_END = II_FUN
|
|
};
|
|
ItemId iid(void) const { return static_cast<ItemId>(_id); }
|
|
|
|
const Location& loc(void) const { return _loc; }
|
|
|
|
protected:
|
|
/// Constructor
|
|
Item(const Location& loc, const ItemId& iid) : ASTNode(iid), _loc(loc) { _flag_1 = false; }
|
|
|
|
public:
|
|
/// Test if item is of type \a T
|
|
template <class T>
|
|
bool isa(void) const {
|
|
return _id == T::iid;
|
|
}
|
|
/// Cast item to type \a T*
|
|
template <class T>
|
|
T* cast(void) {
|
|
assert(isa<T>());
|
|
return static_cast<T*>(this);
|
|
}
|
|
/// Cast expression to type \a const T*
|
|
template <class T>
|
|
const T* cast(void) const {
|
|
assert(isa<T>());
|
|
return static_cast<const T*>(this);
|
|
}
|
|
/// Cast item to type \a T* or NULL if types do not match
|
|
template <class T>
|
|
T* dyn_cast(void) {
|
|
return isa<T>() ? static_cast<T*>(this) : NULL;
|
|
}
|
|
/// Cast item to type \a const T* or NULL if types do not match
|
|
template <class T>
|
|
const T* dyn_cast(void) const {
|
|
return isa<T>() ? static_cast<const T*>(this) : NULL;
|
|
}
|
|
|
|
/// Cast item to type \a T*
|
|
template <class T>
|
|
static T* cast(Item* i) {
|
|
return i == NULL ? NULL : i->cast<T>();
|
|
}
|
|
/// Cast item to type \a const T*
|
|
template <class T>
|
|
static const T* cast(const Item* i) {
|
|
return i == NULL ? NULL : i->cast<T>();
|
|
}
|
|
/// Cast item to type \a T* or NULL if types do not match
|
|
template <class T>
|
|
static T* dyn_cast(Item* i) {
|
|
return i == NULL ? NULL : i->dyn_cast<T>();
|
|
}
|
|
/// Cast item to type \a const T* or NULL if types do not match
|
|
template <class T>
|
|
static const T* dyn_cast(const Item* i) {
|
|
return i == NULL ? NULL : i->dyn_cast<T>();
|
|
}
|
|
|
|
/// Check if item should be removed
|
|
bool removed(void) const { return _flag_1; }
|
|
/// Set flag to remove item
|
|
void remove(void) { _flag_1 = true; }
|
|
/// Unset remove item flag (only possible if not already removed by compact())
|
|
void unremove(void) { _flag_1 = false; }
|
|
};
|
|
|
|
class Model;
|
|
|
|
/// \brief Include item
|
|
class IncludeI : public Item {
|
|
protected:
|
|
/// Filename to include
|
|
ASTString _f;
|
|
/// Model for that file
|
|
Model* _m;
|
|
|
|
public:
|
|
/// The identifier of this item type
|
|
static const ItemId iid = II_INC;
|
|
/// Constructor
|
|
IncludeI(const Location& loc, const ASTString& f);
|
|
/// Access filename
|
|
ASTString f(void) const { return _f; }
|
|
/// Set filename
|
|
void f(const ASTString& nf) { _f = nf; }
|
|
/// Access model
|
|
Model* m(void) const { return _m; }
|
|
/// Set the model
|
|
void m(Model* m0, bool own = true) {
|
|
assert(_m == NULL || m0 == NULL);
|
|
_m = m0;
|
|
_flag_2 = own;
|
|
}
|
|
bool own(void) const { return _flag_2; }
|
|
};
|
|
|
|
/// \brief Variable declaration item
|
|
class VarDeclI : public Item {
|
|
protected:
|
|
/// The declaration expression
|
|
VarDecl* _e;
|
|
|
|
public:
|
|
/// The identifier of this item type
|
|
static const ItemId iid = II_VD;
|
|
/// Constructor
|
|
VarDeclI(const Location& loc, VarDecl* e);
|
|
/// Access expression
|
|
VarDecl* e(void) const { return _e; }
|
|
/// Set expression
|
|
void e(VarDecl* vd) { _e = vd; }
|
|
/// Flag used during compilation
|
|
bool flag(void) const { return _flag_2; }
|
|
/// Set flag used during compilation
|
|
void flag(bool b) { _flag_2 = b; }
|
|
};
|
|
|
|
/// \brief Assign item
|
|
class AssignI : public Item {
|
|
protected:
|
|
/// Identifier of variable to assign to
|
|
ASTString _id;
|
|
/// Expression to assign to the variable
|
|
Expression* _e;
|
|
/// Declaration of the variable to assign to
|
|
VarDecl* _decl;
|
|
|
|
public:
|
|
/// The identifier of this item type
|
|
static const ItemId iid = II_ASN;
|
|
/// Constructor
|
|
AssignI(const Location& loc, const std::string& id, Expression* e);
|
|
/// Access identifier
|
|
ASTString id(void) const { return _id; }
|
|
/// Access expression
|
|
Expression* e(void) const { return _e; }
|
|
/// Set expression
|
|
void e(Expression* e0) { _e = e0; }
|
|
/// Access declaration
|
|
VarDecl* decl(void) const { return _decl; }
|
|
/// Set declaration
|
|
void decl(VarDecl* d) { _decl = d; }
|
|
};
|
|
|
|
/// \brief Constraint item
|
|
class ConstraintI : public Item {
|
|
protected:
|
|
/// Constraint expression
|
|
Expression* _e;
|
|
|
|
public:
|
|
/// The identifier of this item type
|
|
static const ItemId iid = II_CON;
|
|
/// Constructor
|
|
ConstraintI(const Location& loc, Expression* e);
|
|
/// Access expression
|
|
Expression* e(void) const { return _e; }
|
|
/// Set expression
|
|
void e(Expression* e0) { _e = e0; }
|
|
/// Flag used during compilation
|
|
bool flag(void) const { return _flag_2; }
|
|
/// Set flag used during compilation
|
|
void flag(bool b) { _flag_2 = b; }
|
|
};
|
|
|
|
/// \brief Solve item
|
|
class SolveI : public Item {
|
|
protected:
|
|
/// Solve item annotation
|
|
Annotation _ann;
|
|
/// Expression for minimisation/maximisation (or NULL)
|
|
Expression* _e;
|
|
/// Constructor
|
|
SolveI(const Location& loc, Expression* e);
|
|
|
|
public:
|
|
/// The identifier of this item type
|
|
static const ItemId iid = II_SOL;
|
|
/// Type of solving
|
|
enum SolveType { ST_SAT, ST_MIN, ST_MAX };
|
|
/// Allocate solve satisfy item
|
|
static SolveI* sat(const Location& loc);
|
|
/// Allocate solve minimize item
|
|
static SolveI* min(const Location& loc, Expression* e);
|
|
/// Allocate solve maximize item
|
|
static SolveI* max(const Location& loc, Expression* e);
|
|
/// Access solve annotation
|
|
const Annotation& ann(void) const { return _ann; }
|
|
/// Access solve annotation
|
|
Annotation& ann(void) { return _ann; }
|
|
/// Access expression for optimisation
|
|
Expression* e(void) const { return _e; }
|
|
/// Set expression for optimisation
|
|
void e(Expression* e0) { _e = e0; }
|
|
/// Return type of solving
|
|
SolveType st(void) const;
|
|
/// Set type of solving
|
|
void st(SolveType s);
|
|
};
|
|
|
|
/// \brief Output item
|
|
class OutputI : public Item {
|
|
protected:
|
|
/// Expression to output
|
|
Expression* _e;
|
|
|
|
public:
|
|
/// The identifier of this item type
|
|
static const ItemId iid = II_OUT;
|
|
/// Constructor
|
|
OutputI(const Location& loc, Expression* e);
|
|
/// Access expression
|
|
Expression* e(void) const { return _e; }
|
|
/// Update expression
|
|
void e(Expression* e) { _e = e; }
|
|
};
|
|
|
|
class EnvI;
|
|
|
|
/// \brief Function declaration item
|
|
class FunctionI : public Item {
|
|
protected:
|
|
/// Identifier of this function
|
|
ASTString _id;
|
|
/// Type-inst of the return value
|
|
TypeInst* _ti;
|
|
/// List of parameter declarations
|
|
ASTExprVec<VarDecl> _params;
|
|
/// Annotation
|
|
Annotation _ann;
|
|
/// Function body (or NULL)
|
|
Expression* _e;
|
|
/// Whether function is defined in the standard library
|
|
bool _from_stdlib;
|
|
|
|
public:
|
|
/// The identifier of this item type
|
|
static const ItemId iid = II_FUN;
|
|
|
|
/// Type of builtin expression-valued functions
|
|
typedef Expression* (*builtin_e)(EnvI&, Call*);
|
|
/// Type of builtin int-valued functions
|
|
typedef IntVal (*builtin_i)(EnvI&, Call*);
|
|
/// Type of builtin bool-valued functions
|
|
typedef bool (*builtin_b)(EnvI&, Call*);
|
|
/// Type of builtin float-valued functions
|
|
typedef FloatVal (*builtin_f)(EnvI&, Call*);
|
|
/// Type of builtin set-valued functions
|
|
typedef IntSetVal* (*builtin_s)(EnvI&, Call*);
|
|
/// Type of builtin string-valued functions
|
|
typedef std::string (*builtin_str)(EnvI&, Call*);
|
|
|
|
/// Builtin functions (or NULL)
|
|
struct {
|
|
builtin_e e;
|
|
builtin_i i;
|
|
builtin_f f;
|
|
builtin_b b;
|
|
builtin_s s;
|
|
builtin_str str;
|
|
} _builtins;
|
|
|
|
/// Constructor
|
|
FunctionI(const Location& loc, const std::string& id, TypeInst* ti,
|
|
const std::vector<VarDecl*>& params, Expression* e = NULL);
|
|
/// Constructor
|
|
FunctionI(const Location& loc, const ASTString& id, TypeInst* ti,
|
|
const ASTExprVec<VarDecl>& params, Expression* e = NULL);
|
|
|
|
/// Access identifier
|
|
ASTString id(void) const { return _id; }
|
|
/// Access TypeInst
|
|
TypeInst* ti(void) const { return _ti; }
|
|
/// Access parameters
|
|
ASTExprVec<VarDecl> params(void) const { return _params; }
|
|
/// Access annotation
|
|
const Annotation& ann(void) const { return _ann; }
|
|
/// Access annotation
|
|
Annotation& ann(void) { return _ann; }
|
|
/// Access body
|
|
Expression* e(void) const { return _e; }
|
|
/// Set body
|
|
void e(Expression* b) { _e = b; }
|
|
|
|
/** \brief Compute return type given argument types \a ta
|
|
*/
|
|
Type rtype(EnvI& env, const std::vector<Expression*>& ta, bool strictEnums);
|
|
/** \brief Compute return type given argument types \a ta
|
|
*/
|
|
Type rtype(EnvI& env, const std::vector<Type>& ta, bool strictEnums);
|
|
/** \brief Compute expected type of argument \a n given argument types \a ta
|
|
*/
|
|
Type argtype(EnvI& env, const std::vector<Expression*>& ta, int n);
|
|
|
|
/// Return whether function is defined in the standard library
|
|
bool from_stdlib(void) const { return _from_stdlib; };
|
|
|
|
/// Mark for GC
|
|
void mark(void) {
|
|
_gc_mark = 1;
|
|
loc().mark();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* \brief Visitor for expressions
|
|
*
|
|
* This class implements no-ops for all expression types.
|
|
* Override the methods to implement custom behaviour.
|
|
*/
|
|
class EVisitor {
|
|
public:
|
|
/// Visit integer literal
|
|
void vIntLit(const IntLit&) {}
|
|
/// Visit floating point literal
|
|
void vFloatLit(const FloatLit&) {}
|
|
/// Visit Boolean literal
|
|
void vBoolLit(const BoolLit&) {}
|
|
/// Visit set literal
|
|
void vSetLit(const SetLit&) {}
|
|
/// Visit string literal
|
|
void vStringLit(const StringLit&) {}
|
|
/// Visit identifier
|
|
void vId(const Id&) {}
|
|
/// Visit anonymous variable
|
|
void vAnonVar(const AnonVar&) {}
|
|
/// Visit array literal
|
|
void vArrayLit(const ArrayLit&) {}
|
|
/// Visit array access
|
|
void vArrayAccess(const ArrayAccess&) {}
|
|
/// Visit array comprehension
|
|
void vComprehension(const Comprehension&) {}
|
|
/// Visit array comprehension (only generator \a gen_i)
|
|
void vComprehensionGenerator(const Comprehension&, int gen_i) { (void)gen_i; }
|
|
/// Visit if-then-else
|
|
void vITE(const ITE&) {}
|
|
/// Visit binary operator
|
|
void vBinOp(const BinOp&) {}
|
|
/// Visit unary operator
|
|
void vUnOp(const UnOp&) {}
|
|
/// Visit call
|
|
void vCall(const Call&) {}
|
|
/// Visit let
|
|
void vLet(const Let&) {}
|
|
/// Visit variable declaration
|
|
void vVarDecl(const VarDecl&) {}
|
|
/// Visit type inst
|
|
void vTypeInst(const TypeInst&) {}
|
|
/// Visit TIId
|
|
void vTIId(const TIId&) {}
|
|
/// Determine whether to enter node
|
|
bool enter(Expression* e) { return true; }
|
|
/// Exit node after processing has finished
|
|
void exit(Expression* e) {}
|
|
};
|
|
|
|
/// Statically allocated constants
|
|
class Constants {
|
|
private:
|
|
/// Garbage collection root set for constants
|
|
Model* m;
|
|
|
|
public:
|
|
/// Literal true
|
|
BoolLit* lit_true;
|
|
/// Variable bound to true
|
|
VarDecl* var_true;
|
|
/// Literal false
|
|
BoolLit* lit_false;
|
|
/// Variable bound to false
|
|
VarDecl* var_false;
|
|
/// Special variable to signal compiler to ignore result
|
|
VarDecl* var_ignore;
|
|
/// Infinite set
|
|
SetLit* infinity;
|
|
/// Function item used to keep track of redefined variables
|
|
FunctionI* var_redef;
|
|
/// Literal absent value
|
|
Expression* absent;
|
|
/// Identifiers for builtins
|
|
struct {
|
|
ASTString forall;
|
|
ASTString forall_reif;
|
|
ASTString exists;
|
|
ASTString clause;
|
|
ASTString bool2int;
|
|
ASTString int2float;
|
|
ASTString bool2float;
|
|
ASTString assert;
|
|
ASTString trace;
|
|
|
|
ASTString sum;
|
|
ASTString lin_exp;
|
|
ASTString element;
|
|
|
|
ASTString show;
|
|
ASTString fix;
|
|
ASTString output;
|
|
|
|
struct {
|
|
ASTString lin_eq;
|
|
ASTString lin_le;
|
|
ASTString lin_ne;
|
|
ASTString plus;
|
|
ASTString minus;
|
|
ASTString times;
|
|
ASTString div;
|
|
ASTString mod;
|
|
ASTString lt;
|
|
ASTString le;
|
|
ASTString gt;
|
|
ASTString ge;
|
|
ASTString eq;
|
|
ASTString ne;
|
|
} int_;
|
|
|
|
struct {
|
|
ASTString lin_eq;
|
|
ASTString lin_le;
|
|
ASTString lin_ne;
|
|
ASTString plus;
|
|
ASTString minus;
|
|
ASTString times;
|
|
ASTString div;
|
|
ASTString mod;
|
|
ASTString lt;
|
|
ASTString le;
|
|
ASTString gt;
|
|
ASTString ge;
|
|
ASTString eq;
|
|
ASTString ne;
|
|
} int_reif;
|
|
|
|
struct {
|
|
ASTString lin_eq;
|
|
ASTString lin_le;
|
|
ASTString lin_lt;
|
|
ASTString lin_ne;
|
|
ASTString plus;
|
|
ASTString minus;
|
|
ASTString times;
|
|
ASTString div;
|
|
ASTString mod;
|
|
ASTString lt;
|
|
ASTString le;
|
|
ASTString gt;
|
|
ASTString ge;
|
|
ASTString eq;
|
|
ASTString ne;
|
|
ASTString in;
|
|
ASTString dom;
|
|
} float_;
|
|
|
|
struct {
|
|
ASTString lin_eq;
|
|
ASTString lin_le;
|
|
ASTString lin_lt;
|
|
ASTString lin_ne;
|
|
ASTString plus;
|
|
ASTString minus;
|
|
ASTString times;
|
|
ASTString div;
|
|
ASTString mod;
|
|
ASTString lt;
|
|
ASTString le;
|
|
ASTString gt;
|
|
ASTString ge;
|
|
ASTString eq;
|
|
ASTString ne;
|
|
ASTString in;
|
|
} float_reif;
|
|
|
|
ASTString bool_eq;
|
|
ASTString bool_eq_reif;
|
|
ASTString array_bool_or;
|
|
ASTString array_bool_and;
|
|
ASTString bool_clause;
|
|
ASTString bool_clause_reif;
|
|
ASTString bool_xor;
|
|
ASTString set_eq;
|
|
ASTString set_in;
|
|
ASTString set_card;
|
|
ASTString pow;
|
|
|
|
ASTString introduced_var;
|
|
ASTString anonEnumFromStrings;
|
|
} ids;
|
|
|
|
/// Identifiers for Boolean contexts
|
|
struct {
|
|
Id* root;
|
|
Id* pos;
|
|
Id* neg;
|
|
Id* mix;
|
|
} ctx;
|
|
/// Common annotations
|
|
struct {
|
|
Id* output_var;
|
|
ASTString output_array;
|
|
Id* add_to_output;
|
|
Id* output_only;
|
|
Id* mzn_check_var;
|
|
ASTString mzn_check_enum_var;
|
|
Id* is_defined_var;
|
|
ASTString defines_var;
|
|
Id* is_reverse_map;
|
|
Id* promise_total;
|
|
Id* maybe_partial;
|
|
Id* _export;
|
|
ASTString doc_comment;
|
|
ASTString mzn_path;
|
|
ASTString is_introduced;
|
|
Id* user_cut; // MIP
|
|
Id* lazy_constraint; // MIP
|
|
Id* mzn_break_here;
|
|
Id* rhs_from_assignment;
|
|
Id* domain_change_constraint;
|
|
ASTString global_register;
|
|
} ann;
|
|
|
|
/// Command line options
|
|
struct { /// basic MiniZinc command line options
|
|
ASTString cmdlineData_str;
|
|
ASTString cmdlineData_short_str;
|
|
ASTString datafile_str;
|
|
ASTString datafile_short_str;
|
|
ASTString globalsDir_str;
|
|
ASTString globalsDir_alt_str;
|
|
ASTString globalsDir_short_str;
|
|
ASTString help_str;
|
|
ASTString help_short_str;
|
|
ASTString ignoreStdlib_str;
|
|
ASTString include_str;
|
|
ASTString inputFromStdin_str;
|
|
ASTString instanceCheckOnly_str;
|
|
ASTString no_optimize_str;
|
|
ASTString no_optimize_alt_str;
|
|
ASTString no_outputOzn_str;
|
|
ASTString no_outputOzn_short_str;
|
|
ASTString no_typecheck_str;
|
|
ASTString newfzn_str;
|
|
ASTString outputBase_str;
|
|
ASTString outputFznToStdout_str;
|
|
ASTString outputFznToStdout_alt_str;
|
|
ASTString outputOznToFile_str;
|
|
ASTString outputOznToStdout_str;
|
|
ASTString outputFznToFile_str;
|
|
ASTString outputFznToFile_alt_str;
|
|
ASTString outputFznToFile_short_str;
|
|
ASTString rangeDomainsOnly_str;
|
|
ASTString statistics_str;
|
|
ASTString statistics_short_str;
|
|
ASTString stdlib_str;
|
|
ASTString verbose_str;
|
|
ASTString verbose_short_str;
|
|
ASTString version_str;
|
|
ASTString werror_str;
|
|
|
|
struct {
|
|
ASTString all_sols_str;
|
|
ASTString fzn_solver_str;
|
|
} solver;
|
|
|
|
} cli;
|
|
|
|
/// options strings to find setting in Options map
|
|
struct {
|
|
ASTString cmdlineData;
|
|
ASTString datafile;
|
|
ASTString datafiles;
|
|
ASTString fznToStdout;
|
|
ASTString fznToFile;
|
|
ASTString globalsDir;
|
|
ASTString ignoreStdlib;
|
|
ASTString includeDir;
|
|
ASTString includePaths;
|
|
ASTString instanceCheckOnly;
|
|
ASTString inputFromStdin;
|
|
ASTString model;
|
|
ASTString newfzn;
|
|
ASTString noOznOutput;
|
|
ASTString optimize;
|
|
ASTString outputBase;
|
|
ASTString oznToFile;
|
|
ASTString oznToStdout;
|
|
ASTString rangeDomainsOnly;
|
|
ASTString statistics;
|
|
ASTString stdlib;
|
|
ASTString typecheck;
|
|
ASTString verbose;
|
|
ASTString werror;
|
|
|
|
struct {
|
|
ASTString allSols;
|
|
ASTString numSols;
|
|
ASTString threads;
|
|
ASTString fzn_solver;
|
|
ASTString fzn_flags;
|
|
ASTString fzn_flag;
|
|
ASTString fzn_time_limit_ms;
|
|
ASTString fzn_sigint;
|
|
} solver;
|
|
|
|
} opts;
|
|
|
|
/// categories of the command line interface options
|
|
struct {
|
|
ASTString general;
|
|
ASTString io;
|
|
ASTString solver;
|
|
ASTString translation;
|
|
} cli_cat;
|
|
|
|
/// Keep track of allocated integer literals
|
|
std::unordered_map<IntVal, WeakRef> integerMap;
|
|
/// Keep track of allocated float literals
|
|
std::unordered_map<FloatVal, WeakRef> floatMap;
|
|
/// Constructor
|
|
Constants(void);
|
|
/// Return shared BoolLit
|
|
BoolLit* boollit(bool b) { return b ? lit_true : lit_false; }
|
|
static const int max_array_size = std::numeric_limits<int>::max() / 2;
|
|
};
|
|
|
|
/// Return static instance
|
|
Constants& constants(void);
|
|
|
|
} // namespace MiniZinc
|
|
|
|
#include <minizinc/ast.hpp>
|
|
|
|
#endif
|