/*++ Copyright (c) 2012 Microsoft Corporation Module Name: FuncDecl.cs Abstract: Z3 Managed API: Function Declarations Author: Christoph Wintersteiger (cwinter) 2012-03-16 Notes: --*/ using System; using System.Diagnostics.Contracts; namespace Microsoft.Z3 { /// /// Function declarations. /// [ContractVerification(true)] public class FuncDecl : AST { /// /// Comparison operator. /// /// True if and share the same context and are equal, false otherwise. public static bool operator ==(FuncDecl a, FuncDecl b) { return Object.ReferenceEquals(a, b) || (!Object.ReferenceEquals(a, null) && !Object.ReferenceEquals(b, null) && a.Context.nCtx == b.Context.nCtx && Native.Z3_is_eq_func_decl(a.Context.nCtx, a.NativeObject, b.NativeObject) != 0); } /// /// Comparison operator. /// /// True if and do not share the same context or are not equal, false otherwise. public static bool operator !=(FuncDecl a, FuncDecl b) { return !(a == b); } /// /// Object comparison. /// public override bool Equals(object o) { FuncDecl casted = o as FuncDecl; if (casted == null) return false; return this == casted; } /// /// A hash code. /// public override int GetHashCode() { return base.GetHashCode(); } /// /// A string representations of the function declaration. /// public override string ToString() { return Native.Z3_func_decl_to_string(Context.nCtx, NativeObject); } /// /// Returns a unique identifier for the function declaration. /// new public uint Id { get { return Native.Z3_get_func_decl_id(Context.nCtx, NativeObject); } } /// /// The arity of the function declaration /// public uint Arity { get { return Native.Z3_get_arity(Context.nCtx, NativeObject); } } /// /// The size of the domain of the function declaration /// /// public uint DomainSize { get { return Native.Z3_get_domain_size(Context.nCtx, NativeObject); } } /// /// The domain of the function declaration /// public Sort[] Domain { get { Contract.Ensures(Contract.Result() != null); var n = DomainSize; Sort[] res = new Sort[n]; for (uint i = 0; i < n; i++) res[i] = Sort.Create(Context, Native.Z3_get_domain(Context.nCtx, NativeObject, i)); return res; } } /// /// The range of the function declaration /// public Sort Range { get { Contract.Ensures(Contract.Result() != null); return Sort.Create(Context, Native.Z3_get_range(Context.nCtx, NativeObject)); } } /// /// The kind of the function declaration. /// public Z3_decl_kind DeclKind { get { return (Z3_decl_kind)Native.Z3_get_decl_kind(Context.nCtx, NativeObject); } } /// /// The name of the function declaration /// public Symbol Name { get { Contract.Ensures(Contract.Result() != null); return Symbol.Create(Context, Native.Z3_get_decl_name(Context.nCtx, NativeObject)); } } /// /// The number of parameters of the function declaration /// public uint NumParameters { get { return Native.Z3_get_decl_num_parameters(Context.nCtx, NativeObject); } } /// /// The parameters of the function declaration /// public Parameter[] Parameters { get { Contract.Ensures(Contract.Result() != null); uint num = NumParameters; Parameter[] res = new Parameter[num]; for (uint i = 0; i < num; i++) { Z3_parameter_kind k = (Z3_parameter_kind)Native.Z3_get_decl_parameter_kind(Context.nCtx, NativeObject, i); switch (k) { case Z3_parameter_kind.Z3_PARAMETER_INT: res[i] = new Parameter(k, Native.Z3_get_decl_int_parameter(Context.nCtx, NativeObject, i)); break; case Z3_parameter_kind.Z3_PARAMETER_DOUBLE: res[i] = new Parameter(k, Native.Z3_get_decl_double_parameter(Context.nCtx, NativeObject, i)); break; case Z3_parameter_kind.Z3_PARAMETER_SYMBOL: res[i] = new Parameter(k, Symbol.Create(Context, Native.Z3_get_decl_symbol_parameter(Context.nCtx, NativeObject, i))); break; case Z3_parameter_kind.Z3_PARAMETER_SORT: res[i] = new Parameter(k, Sort.Create(Context, Native.Z3_get_decl_sort_parameter(Context.nCtx, NativeObject, i))); break; case Z3_parameter_kind.Z3_PARAMETER_AST: res[i] = new Parameter(k, new AST(Context, Native.Z3_get_decl_ast_parameter(Context.nCtx, NativeObject, i))); break; case Z3_parameter_kind.Z3_PARAMETER_FUNC_DECL: res[i] = new Parameter(k, new FuncDecl(Context, Native.Z3_get_decl_func_decl_parameter(Context.nCtx, NativeObject, i))); break; case Z3_parameter_kind.Z3_PARAMETER_RATIONAL: res[i] = new Parameter(k, Native.Z3_get_decl_rational_parameter(Context.nCtx, NativeObject, i)); break; default: throw new Z3Exception("Unknown function declaration parameter kind encountered"); } } return res; } } /// /// Function declarations can have Parameters associated with them. /// public class Parameter { readonly private Z3_parameter_kind kind; readonly private int i; readonly private double d; readonly private Symbol sym; readonly private Sort srt; readonly private AST ast; readonly private FuncDecl fd; readonly private string r; /// The int value of the parameter. public int Int { get { if (ParameterKind != Z3_parameter_kind.Z3_PARAMETER_INT) throw new Z3Exception("parameter is not an int"); return i; } } /// The double value of the parameter. public double Double { get { if (ParameterKind != Z3_parameter_kind.Z3_PARAMETER_DOUBLE) throw new Z3Exception("parameter is not a double "); return d; } } /// The Symbol value of the parameter. public Symbol Symbol { get { if (ParameterKind != Z3_parameter_kind.Z3_PARAMETER_SYMBOL) throw new Z3Exception("parameter is not a Symbol"); return sym; } } /// The Sort value of the parameter. public Sort Sort { get { if (ParameterKind != Z3_parameter_kind.Z3_PARAMETER_SORT) throw new Z3Exception("parameter is not a Sort"); return srt; } } /// The AST value of the parameter. public AST AST { get { if (ParameterKind != Z3_parameter_kind.Z3_PARAMETER_AST) throw new Z3Exception("parameter is not an AST"); return ast; } } /// The FunctionDeclaration value of the parameter. public FuncDecl FuncDecl { get { if (ParameterKind != Z3_parameter_kind.Z3_PARAMETER_FUNC_DECL) throw new Z3Exception("parameter is not a function declaration"); return fd; } } /// The rational string value of the parameter. public string Rational { get { if (ParameterKind != Z3_parameter_kind.Z3_PARAMETER_RATIONAL) throw new Z3Exception("parameter is not a rational string"); return r; } } /// /// The kind of the parameter. /// public Z3_parameter_kind ParameterKind { get { return kind; } } #region Internal internal Parameter(Z3_parameter_kind k, int i) { this.kind = k; this.i = i; } internal Parameter(Z3_parameter_kind k, double d) { this.kind = k; this.d = d; } internal Parameter(Z3_parameter_kind k, Symbol s) { this.kind = k; this.sym = s; } internal Parameter(Z3_parameter_kind k, Sort s) { this.kind = k; this.srt = s; } internal Parameter(Z3_parameter_kind k, AST a) { this.kind = k; this.ast = a; } internal Parameter(Z3_parameter_kind k, FuncDecl fd) { this.kind = k; this.fd = fd; } internal Parameter(Z3_parameter_kind k, string r) { this.kind = k; this.r = r; } #endregion } #region Internal internal FuncDecl(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } internal FuncDecl(Context ctx, Symbol name, Sort[] domain, Sort range) : base(ctx, Native.Z3_mk_func_decl(ctx.nCtx, name.NativeObject, AST.ArrayLength(domain), AST.ArrayToNative(domain), range.NativeObject)) { Contract.Requires(ctx != null); Contract.Requires(name != null); Contract.Requires(range != null); } internal FuncDecl(Context ctx, string prefix, Sort[] domain, Sort range) : base(ctx, Native.Z3_mk_fresh_func_decl(ctx.nCtx, prefix, AST.ArrayLength(domain), AST.ArrayToNative(domain), range.NativeObject)) { Contract.Requires(ctx != null); Contract.Requires(range != null); } #if DEBUG internal override void CheckNativeObject(IntPtr obj) { if (Native.Z3_get_ast_kind(Context.nCtx, obj) != (uint)Z3_ast_kind.Z3_FUNC_DECL_AST) throw new Z3Exception("Underlying object is not a function declaration"); base.CheckNativeObject(obj); } #endif #endregion /// /// Create expression that applies function to arguments. /// /// /// public Expr this[params Expr[] args] { get { Contract.Requires(args == null || Contract.ForAll(args, a => a != null)); return Apply(args); } } /// /// Create expression that applies function to arguments. /// /// /// public Expr Apply(params Expr[] args) { Contract.Requires(args == null || Contract.ForAll(args, a => a != null)); Context.CheckContextMatch(args); return Expr.Create(Context, this, args); } } }