To add a “builtin” C++ operation to bali-phy’s Haskell code, you need to do two things: 1.. write the code for function in a C++ file. 2. declare the C++ builtin function in a Haskell module. The second step is necessary to make the C++ function visible in Haskell.
A builtin is declared via the following syntax:
import bpcall "module_name:cpp_func_name" haskell_name :: Type foreign
For example, the Haskell function poisson_density
is
declared with the following line from haskell/Distributions.hs:
import bpcall "Distribution:poisson_density" poisson_density :: Double -> Int -> LogDouble foreign
The quoted string specifies the loadable module that contains the function and the C++ function name. Since this function is in the module “Distribution”, its source code goes in src/builtins/Distribution.cc.
The C++ function name is obtained by adding
builtin_function_
in front of poisson_density
.
So the C++ function will be called
builtin_function_poisson_density
.
The rest of the declaration specifies the Haskell name
(poisson_density
) and the type
(Double -> Int -> Double
).
The C++ function for a builtin must be defined in one of the C++
files in the src/builtins
directory, and the function name must begin with
builtin_function_
. The function must also be declared
extern "C"
(to avoid name mangling).
For example, the poisson density function is written in src/builtins/Distribution.cc as follows:
extern "C" closure builtin_function_poisson_density(OperationArgs& Args)
{
double mu = Args.evaluate(0).as_double();
int n = Args.evaluate(1).as_int();
return { poisson_pdf(mu,n) };
}
Input:
OperationArgs& Args
argument.n
th argument is fetched by calling
Args.evaluate(n)
, and is of type
expression_ref
(src/computation/expression/expression_ref.H)expression_ref
can be converted to
int
, double
, or log_double_t
using the methods .as_int()
, .as_double()
and
.as_log_double()
.Output:
closure
object (src/computation/closure.H)double
or
int
. Here an explicit conversion is invoked by surrouding a
log_double_t
with curly braces.log_double_t
This is a positive real number represented in terms of its logarithm. Operators have been defined so that you can multiply, add, subtract, and divide this type.
Object
All C++ objects are accessed from Haskell inherit from this type.
expression_ref
An expression ref is basically either an atomic value or an Object
followed by a list of expression_ref
s
See src/computation/expression/expression_ref.H
closure
A closure is an expression_ref
with an environment.