Customisation
A major change that has occurred as the package reaches 1.0.0 is that every part of the transpiler becomes configurable. In this article, we discuss how one could create custom rewriting rules and deparsers for specific use.
#
Custom rewriting rulesTo create a rewriting rule, we use the make_rule
function. It takes two strings and returns a function that rewrites the first string into the second string appeared in a language object.
A custom rewriter is usually needed when one wants to do arithmetic of a special class of objects offered by some JavaScript library. For example, in the case of math.js, addition is expected to be carried out as math.add(x, y)
to allow for adding together different types of objects (like vectors and matrices). In such case, we would define the rule as follows.
Once the rule is created, it can be passed to the transpiler using the rules
argument. Specifically,
Here is an example with tensorflow.js:
#
Custom deparsersA custom deparser is needed when there is certain construct that cannot be expressed as a simple rewriting rule. For example, consider the for-loop, in R, it looks like:
and the corresponding version in JavaScript is:
In such case, the transpilation cannot be done with a simple rewriting rule, and a custom deparser is needed. To create a deparser, two functions are needed: a predicate function that recognises the function-call trigger and a deparse function that performs the transpilation.
The predicate function must take an “expression” returned by parse_expr
(imported from rlang::parse_expr
) and return a logical vector of length one.
The deparse function takes the same input as the predicate function and returns a character string. Note that ...
must be provided to stay consistent with other deparsers provided by this package. For illustration purposes, we capitalise “of” to distinguish the custom deparser with the one provided by the package.
To integrate your custom deparser into the “master” deparser provided by this package, deparse_js
, first replace the deparse1
call in the line marked “Note 1” by deparse_js
, and combine the predicate function and the deparse function with make_deparser
, then add your deparser to any of the existing lists of deparsers, i.e. basic_deparsers()
/ default_deparsers()
(or you can build your list from scratch too). Here is the full listing of the resulting code: