Z3::FuncDecl
Inherits Reference < Object
A function symbol - what SMT-LIB's declare-fun declares, and what a model hands
back when it has decided what a function does.
Applying one with #[] gives an expression of the declared range sort, which is
only known at runtime, so the result is an AnyExpr - a union - and has to be
narrowed before anything at all can be done with it, == included:
f = Z3.function("f", Z3::IntSort, Z3::IntSort)
x = f[3].as(Z3::IntExpr)
solver.assert x == 10
This is the tax on there being no common Z3::Expr base class yet - see _TODO.md.
Constructors
Last sort is the range, the ones before it are the domain, the same order
SMT-LIB's declare-fun uses
Class methods
Z3's answer for #recursive? is the decl kind Z3_OP_RECURSIVE, whose numeric
value sits at the far end of an enum which grows between releases - so rather
than writing the number down, we make one recursive declaration and ask Z3 what
kind it came out as. Leaving it undefined is safe: nothing applies it, so no
solver ever has to unfold it and no model mentions it.
Instance methods
Z3 hash-conses declarations, so two decls of the same name and signature are one
and the same pointer. Unlike an expression there's nothing for == to build - a
declaration is not a value - so this answers the question directly, and a
FuncDecl works as a Hash key.
Applies the function. Arguments are cast into the declared domain sorts, so
f[3] works wherever f[IntSort[3]] does.
Gives a recursive declaration its body - the define-fun-rec half of
Z3.rec_function. The block gets one fresh variable per domain sort, as an
Array because the arity is only known at runtime, and returns the body - which
may call this very function:
fact = Z3.rec_function("fact", Z3::IntSort, Z3::IntSort)
fact.define do |args|
n = args[0].as(Z3::IntExpr)
(n <= 0).ite(1, n * fact[n - 1].as(Z3::IntExpr))
end
The Ruby gem takes the body as a block on Z3.RecFunction too. Here it's always
this second step, because Crystal has no way to pass a variable number of block
arguments and mutual recursion needs the two-step form anyway.
Only a declaration made by Z3.rec_function can be defined; Z3 says so itself
for any other, which is a better error than anything we could check for here.
Whether this was declared by Z3.rec_function, which is worth asking because Z3
hands those back in places nothing else shows up - see Model#funcs.