/*++ Copyright (c) 2012 Microsoft Corporation Module Name: Sort.cs Abstract: Z3 Managed API: Sorts Author: Christoph Wintersteiger (cwinter) 2012-03-15 Notes: --*/ using System; using System.Diagnostics.Contracts; namespace Microsoft.Z3 { /// /// The Sort class implements type information for ASTs. /// [ContractVerification(true)] public class Sort : AST { /// /// Comparison operator. /// /// A Sort /// A Sort /// True if and are from the same context /// and represent the same sort; false otherwise. public static bool operator ==(Sort a, Sort b) { return Object.ReferenceEquals(a, b) || (!Object.ReferenceEquals(a, null) && !Object.ReferenceEquals(b, null) && a.Context == b.Context && Native.Z3_is_eq_sort(a.Context.nCtx, a.NativeObject, b.NativeObject) != 0); } /// /// Comparison operator. /// /// A Sort /// A Sort /// True if and are not from the same context /// or represent different sorts; false otherwise. public static bool operator !=(Sort a, Sort b) { return !(a == b); } /// /// Equality operator for objects of type Sort. /// /// /// public override bool Equals(object o) { Sort casted = o as Sort; if (casted == null) return false; return this == casted; } /// /// Hash code generation for Sorts /// /// A hash code public override int GetHashCode() { return base.GetHashCode(); } /// /// Returns a unique identifier for the sort. /// new public uint Id { get { return Native.Z3_get_sort_id(Context.nCtx, NativeObject); } } /// /// The kind of the sort. /// public Z3_sort_kind SortKind { get { return (Z3_sort_kind)Native.Z3_get_sort_kind(Context.nCtx, NativeObject); } } /// /// The name of the sort /// public Symbol Name { get { Contract.Ensures(Contract.Result() != null); return Symbol.Create(Context, Native.Z3_get_sort_name(Context.nCtx, NativeObject)); } } /// /// A string representation of the sort. /// public override string ToString() { return Native.Z3_sort_to_string(Context.nCtx, NativeObject); } #region Internal /// /// Sort constructor /// internal protected Sort(Context ctx) : base(ctx) { Contract.Requires(ctx != null); } internal Sort(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } #if DEBUG internal override void CheckNativeObject(IntPtr obj) { if (Native.Z3_get_ast_kind(Context.nCtx, obj) != (uint)Z3_ast_kind.Z3_SORT_AST) throw new Z3Exception("Underlying object is not a sort"); base.CheckNativeObject(obj); } #endif [ContractVerification(true)] new internal static Sort Create(Context ctx, IntPtr obj) { Contract.Requires(ctx != null); Contract.Ensures(Contract.Result() != null); switch ((Z3_sort_kind)Native.Z3_get_sort_kind(ctx.nCtx, obj)) { case Z3_sort_kind.Z3_ARRAY_SORT: return new ArraySort(ctx, obj); case Z3_sort_kind.Z3_BOOL_SORT: return new BoolSort(ctx, obj); case Z3_sort_kind.Z3_BV_SORT: return new BitVecSort(ctx, obj); case Z3_sort_kind.Z3_DATATYPE_SORT: return new DatatypeSort(ctx, obj); case Z3_sort_kind.Z3_INT_SORT: return new IntSort(ctx, obj); case Z3_sort_kind.Z3_REAL_SORT: return new RealSort(ctx, obj); case Z3_sort_kind.Z3_UNINTERPRETED_SORT: return new UninterpretedSort(ctx, obj); case Z3_sort_kind.Z3_FINITE_DOMAIN_SORT: return new FiniteDomainSort(ctx, obj); case Z3_sort_kind.Z3_RELATION_SORT: return new RelationSort(ctx, obj); default: throw new Z3Exception("Unknown sort kind"); } } #endregion } /// /// A Boolean sort. /// public class BoolSort : Sort { #region Internal internal BoolSort(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } internal BoolSort(Context ctx) : base(ctx, Native.Z3_mk_bool_sort(ctx.nCtx)) { Contract.Requires(ctx != null); } #endregion }; /// /// An arithmetic sort, i.e., Int or Real. /// public class ArithSort : Sort { #region Internal internal ArithSort(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } #endregion }; /// /// An Integer sort /// public class IntSort : ArithSort { #region Internal internal IntSort(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } internal IntSort(Context ctx) : base(ctx, Native.Z3_mk_int_sort(ctx.nCtx)) { Contract.Requires(ctx != null); } #endregion } /// /// A real sort /// public class RealSort : ArithSort { #region Internal internal RealSort(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } internal RealSort(Context ctx) : base(ctx, Native.Z3_mk_real_sort(ctx.nCtx)) { Contract.Requires(ctx != null); } #endregion } /// /// Bit-vector sorts. /// public class BitVecSort : Sort { /// /// The size of the bit-vector sort. /// public uint Size { get { return Native.Z3_get_bv_sort_size(Context.nCtx, NativeObject); } } #region Internal internal BitVecSort(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } internal BitVecSort(Context ctx, uint size) : base(ctx, Native.Z3_mk_bv_sort(ctx.nCtx, size)) { Contract.Requires(ctx != null); } #endregion }; /// /// Array sorts. /// [ContractVerification(true)] public class ArraySort : Sort { /// /// The domain of the array sort. /// public Sort Domain { get { Contract.Ensures(Contract.Result() != null); return Sort.Create(Context, Native.Z3_get_array_sort_domain(Context.nCtx, NativeObject)); } } /// /// The range of the array sort. /// public Sort Range { get { Contract.Ensures(Contract.Result() != null); return Sort.Create(Context, Native.Z3_get_array_sort_range(Context.nCtx, NativeObject)); } } #region Internal internal ArraySort(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } internal ArraySort(Context ctx, Sort domain, Sort range) : base(ctx, Native.Z3_mk_array_sort(ctx.nCtx, domain.NativeObject, range.NativeObject)) { Contract.Requires(ctx != null); Contract.Requires(domain != null); Contract.Requires(range != null); } #endregion }; /// /// Datatype sorts. /// [ContractVerification(true)] public class DatatypeSort : Sort { /// /// The number of constructors of the datatype sort. /// public uint NumConstructors { get { return Native.Z3_get_datatype_sort_num_constructors(Context.nCtx, NativeObject); } } /// /// The constructors. /// public FuncDecl[] Constructors { get { Contract.Ensures(Contract.Result() != null); uint n = NumConstructors; FuncDecl[] res = new FuncDecl[n]; for (uint i = 0; i < n; i++) res[i] = new FuncDecl(Context, Native.Z3_get_datatype_sort_constructor(Context.nCtx, NativeObject, i)); return res; } } /// /// The recognizers. /// public FuncDecl[] Recognizers { get { Contract.Ensures(Contract.Result() != null); uint n = NumConstructors; FuncDecl[] res = new FuncDecl[n]; for (uint i = 0; i < n; i++) res[i] = new FuncDecl(Context, Native.Z3_get_datatype_sort_recognizer(Context.nCtx, NativeObject, i)); return res; } } /// /// The constructor accessors. /// public FuncDecl[][] Accessors { get { Contract.Ensures(Contract.Result() != null); uint n = NumConstructors; FuncDecl[][] res = new FuncDecl[n][]; for (uint i = 0; i < n; i++) { FuncDecl fd = new FuncDecl(Context, Native.Z3_get_datatype_sort_constructor(Context.nCtx, NativeObject, i)); uint ds = fd.DomainSize; FuncDecl[] tmp = new FuncDecl[ds]; for (uint j = 0; j < ds; j++) tmp[j] = new FuncDecl(Context, Native.Z3_get_datatype_sort_constructor_accessor(Context.nCtx, NativeObject, i, j)); res[i] = tmp; } return res; } } #region Internal internal DatatypeSort(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } internal DatatypeSort(Context ctx, Symbol name, Constructor[] constructors) : base(ctx, Native.Z3_mk_datatype(ctx.nCtx, name.NativeObject, (uint)constructors.Length, ArrayToNative(constructors))) { Contract.Requires(ctx != null); Contract.Requires(name != null); Contract.Requires(constructors != null); } #endregion }; /// /// Uninterpreted Sorts /// public class UninterpretedSort : Sort { #region Internal internal UninterpretedSort(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } internal UninterpretedSort(Context ctx, Symbol s) : base(ctx, Native.Z3_mk_uninterpreted_sort(ctx.nCtx, s.NativeObject)) { Contract.Requires(ctx != null); Contract.Requires(s != null); } #endregion } /// /// Tuple sorts. /// [ContractVerification(true)] public class TupleSort : Sort { /// /// The constructor function of the tuple. /// public FuncDecl MkDecl { get { Contract.Ensures(Contract.Result() != null); return new FuncDecl(Context, Native.Z3_get_tuple_sort_mk_decl(Context.nCtx, NativeObject)); } } /// /// The number of fields in the tuple. /// public uint NumFields { get { return Native.Z3_get_tuple_sort_num_fields(Context.nCtx, NativeObject); } } /// /// The field declarations. /// public FuncDecl[] FieldDecls { get { Contract.Ensures(Contract.Result() != null); uint n = NumFields; FuncDecl[] res = new FuncDecl[n]; for (uint i = 0; i < n; i++) res[i] = new FuncDecl(Context, Native.Z3_get_tuple_sort_field_decl(Context.nCtx, NativeObject, i)); return res; } } #region Internal internal TupleSort(Context ctx, Symbol name, uint numFields, Symbol[] fieldNames, Sort[] fieldSorts) : base(ctx) { Contract.Requires(ctx != null); Contract.Requires(name != null); IntPtr t = IntPtr.Zero; NativeObject = Native.Z3_mk_tuple_sort(ctx.nCtx, name.NativeObject, numFields, Symbol.ArrayToNative(fieldNames), AST.ArrayToNative(fieldSorts), ref t, new IntPtr[numFields]); } #endregion }; /// /// Enumeration sorts. /// [ContractVerification(true)] public class EnumSort : Sort { /// /// The function declarations of the constants in the enumeration. /// public FuncDecl[] ConstDecls { get { Contract.Ensures(Contract.Result() != null); return _constdecls; } } /// /// The constants in the enumeration. /// public Expr[] Consts { get { Contract.Ensures(Contract.Result() != null); return _consts; } } /// /// The test predicates for the constants in the enumeration. /// public FuncDecl[] TesterDecls { get { Contract.Ensures(Contract.Result() != null); return _testerdecls; } } #region Object Invariant [ContractInvariantMethod] private void ObjectInvariant() { Contract.Invariant(this._constdecls != null); Contract.Invariant(this._testerdecls != null); Contract.Invariant(this._consts != null); } #endregion #region Internal readonly private FuncDecl[] _constdecls = null, _testerdecls = null; readonly private Expr[] _consts = null; internal EnumSort(Context ctx, Symbol name, Symbol[] enumNames) : base(ctx) { Contract.Requires(ctx != null); Contract.Requires(name != null); Contract.Requires(enumNames != null); int n = enumNames.Length; IntPtr[] n_constdecls = new IntPtr[n]; IntPtr[] n_testers = new IntPtr[n]; NativeObject = Native.Z3_mk_enumeration_sort(ctx.nCtx, name.NativeObject, (uint)n, Symbol.ArrayToNative(enumNames), n_constdecls, n_testers); _constdecls = new FuncDecl[n]; for (uint i = 0; i < n; i++) _constdecls[i] = new FuncDecl(ctx, n_constdecls[i]); _testerdecls = new FuncDecl[n]; for (uint i = 0; i < n; i++) _testerdecls[i] = new FuncDecl(ctx, n_testers[i]); _consts = new Expr[n]; for (uint i = 0; i < n; i++) _consts[i] = ctx.MkApp(_constdecls[i]); } #endregion }; /// /// List sorts. /// [ContractVerification(true)] public class ListSort : Sort { /// /// The declaration of the nil function of this list sort. /// public FuncDecl NilDecl { get { Contract.Ensures(Contract.Result() != null); return nilDecl; } } /// /// The empty list. /// public Expr Nil { get { Contract.Ensures(Contract.Result() != null); return nilConst; } } /// /// The declaration of the isNil function of this list sort. /// public FuncDecl IsNilDecl { get { Contract.Ensures(Contract.Result() != null); return isNilDecl; } } /// /// The declaration of the cons function of this list sort. /// public FuncDecl ConsDecl { get { Contract.Ensures(Contract.Result() != null); return consDecl; } } /// /// The declaration of the isCons function of this list sort. /// /// public FuncDecl IsConsDecl { get { Contract.Ensures(Contract.Result() != null); return isConsDecl; } } /// /// The declaration of the head function of this list sort. /// public FuncDecl HeadDecl { get { Contract.Ensures(Contract.Result() != null); return headDecl; } } /// /// The declaration of the tail function of this list sort. /// public FuncDecl TailDecl { get { Contract.Ensures(Contract.Result() != null); return tailDecl; } } #region Object Invariant [ContractInvariantMethod] private void ObjectInvariant() { Contract.Invariant(nilConst != null); Contract.Invariant(nilDecl != null); Contract.Invariant(isNilDecl != null); Contract.Invariant(consDecl != null); Contract.Invariant(isConsDecl != null); Contract.Invariant(headDecl != null); Contract.Invariant(tailDecl != null); } #endregion #region Internal readonly private FuncDecl nilDecl, isNilDecl, consDecl, isConsDecl, headDecl, tailDecl; readonly private Expr nilConst; internal ListSort(Context ctx, Symbol name, Sort elemSort) : base(ctx) { Contract.Requires(ctx != null); Contract.Requires(name != null); Contract.Requires(elemSort != null); IntPtr inil = IntPtr.Zero, iisnil = IntPtr.Zero, icons = IntPtr.Zero, iiscons = IntPtr.Zero, ihead = IntPtr.Zero, itail = IntPtr.Zero; NativeObject = Native.Z3_mk_list_sort(ctx.nCtx, name.NativeObject, elemSort.NativeObject, ref inil, ref iisnil, ref icons, ref iiscons, ref ihead, ref itail); nilDecl = new FuncDecl(ctx, inil); isNilDecl = new FuncDecl(ctx, iisnil); consDecl = new FuncDecl(ctx, icons); isConsDecl = new FuncDecl(ctx, iiscons); headDecl = new FuncDecl(ctx, ihead); tailDecl = new FuncDecl(ctx, itail); nilConst = ctx.MkConst(nilDecl); } #endregion }; /// /// Relation sorts. /// [ContractVerification(true)] public class RelationSort : Sort { /// /// The arity of the relation sort. /// public uint Arity { get { return Native.Z3_get_relation_arity(Context.nCtx, NativeObject); } } /// /// The sorts of the columns of the relation sort. /// public Sort[] ColumnSorts { get { Contract.Ensures(Contract.Result() != null); if (m_columnSorts != null) return m_columnSorts; uint n = Arity; Sort[] res = new Sort[n]; for (uint i = 0; i < n; i++) res[i] = Sort.Create(Context, Native.Z3_get_relation_column(Context.nCtx, NativeObject, i)); return res; } } #region Internal private Sort[] m_columnSorts = null; internal RelationSort(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } #endregion } /// /// Finite domain sorts. /// [ContractVerification(true)] public class FiniteDomainSort : Sort { /// /// The size of the finite domain sort. /// public ulong Size { get { ulong res = 0; Native.Z3_get_finite_domain_sort_size(Context.nCtx, NativeObject, ref res); return res; } } #region Internal internal FiniteDomainSort(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } internal FiniteDomainSort(Context ctx, Symbol name, ulong size) : base(ctx, Native.Z3_mk_finite_domain_sort(ctx.nCtx, name.NativeObject, size)) { Contract.Requires(ctx != null); Contract.Requires(name != null); } #endregion } /// /// Set sorts. /// [ContractVerification(true)] public class SetSort : Sort { #region Internal internal SetSort(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } internal SetSort(Context ctx, Sort ty) : base(ctx, Native.Z3_mk_set_sort(ctx.nCtx, ty.NativeObject)) { Contract.Requires(ctx != null); Contract.Requires(ty != null); } #endregion } }