This guide first briefly describes the size processing system in NIMBLE. It then describes the process of adding a new size processor and lists some commonly used size processors. Note that NIMBLE’s size processing functionality can largely be found in genCpp_sizeProcessing.R.

Size Processing Overview

The size processing step in NIMBLE proceeds by traveling recursively through the syntax tree, annotating each node with dimensionality, type, size expressions, and eigenizability (“yes”, “no”, or “maybe” for conversion to C++ Eigen package code). It also generates run-time size checks, inserts intermediate variables, and populates the local symbol table with locally created objects.

Nodes of the syntax tree are represented as exprClass objects. Each node of the syntax tree (as given by the code argument to a size processor) should exit the size processor with the following fields set:

Two useful fields that should only be modified with care are:

Note that some or all of these fields may be set by other functions called within a size processor (e.g. makeSizeExpressions()), and as such do not necessarily need to be explicitly set within the processor itself. (I’m not sure what this statement means. Can you clarify it?)

Typically the first step in a size processor is to recurse on its arguments (see below), which means that the arguments can be counted on to have the above fields set. e.g. code$args[[1]]$nDim will be the number of dimensions of the first argument (or whatever is returned by it).

Size processors collect additional expressions, called asserts, that are later inserted into the syntax tree and become lines of code before or after the line being processed. asserts may be collected for each line of code that is size processed, and the lines of code generated by the asserts can be inserted either before (by default) or after (if wrapped in after()) the expression they are assert-ed from. asserts are frequently run-time size checks, but can also be used to create intermediate variables, among other uses. For an example of generating asserts that go both before and after a line of code, see the sizeasDoublePtr() size processor.

Adding a New Size Processor

Tips, tricks, and useful size processors

arg2nDim <- if(inherits(code$args[[2]], 'exprClass')) code$args[[2]]$nDim else 0