--- title: "The R.lua module" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{The R.lua module} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` *For the getting started guide, see [Introduction to `luajr`](luajr.html).* ## Introduction This vignette is for advanced R users who know how to use R's API from C code. If you normally use R without C, this vignette may not make a lot of sense to you. If you use the **Rcpp** or **cpp11** packages to interface C++ code with R, but have not used R's C API directly, this vignette may not make sense to you either. Just a warning! The **luajr** package ships with two Lua modules included. The more commonly-used module is `luajr.lua`, which offers convenience and higher-level interaction with R. That module is described in the vignette [The luajr.lua module](luajr-module.html). But, if you need lower-level access to R's internals from Lua, then `R.lua` may be helpful to you. The `R.lua` module provides access to R's C API from Lua. If you understand what each element of the following C code does: ```c SEXP s = PROTECT(Rf_allocVector(VECSXP, 3)); ``` then you may find this vignette helpful. If not, you will need to thoroughly consult the [Writing R Extensions](https://cran.r-project.org/doc/manuals/r-release/R-exts.html) manual before proceeding, because this vignette assumes you are already familiar with R's C API. ## Loading R.lua Any Lua state that has been opened through the **luajr** package automatically loads the `luajr.lua` module, but **the `R.lua` module needs to be loaded** **explicitly before use**. The `R.lua` module can be loaded in Lua code like so: ```Lua R = require "R" ``` The above line of Lua code opens the `R.lua` module and loads it into a global Lua variable `R`. Once that line has been executed in a Lua state, you can start to use the R functions and types that are part of the module. Of course, you can assign the module to a local variable instead. ## R.sexp R's C API represents R values using the type `SEXP`, meaning "S expression". The `SEXP` type is a pointer to an opaque C struct `SEXPREC` -- see [R Internals](https://cran.r-project.org/doc/manuals/r-release/R-ints.html) for full details. Within Lua code, `R.sexp` is an alias for the `SEXP` type (through LuaJIT's ctype mechanism), which means you can use Lua variables of type `R.sexp` to pass to R's API functions. ## Functions `R.lua` exposes some (but not all) of R's C API functions. The naming of R's C API functions is all over the place. Some functions have no prefix, others have the prefix `R_`, and still others have the prefix `Rf_`, with no obvious pattern. Function names can be UPPER_CASE, lower_case, camelCase or TitleCase. It can be confusing. `R.lua` drops all `R_` and `Rf_` prefixes because the module is typically loaded into a table named `R`, so `R.Rf_allocVector` would seem redundant (instead it is `R.allocVector`). But the case of the function name is kept as-is for consistency with the C API, and when there is a familiar C macro that maps to a function, the case of the macro is preferred (for example, `PROTECT` in C is a macro mapping to the function `Rf_protect`; the corresponding `R.lua` function is named `R.PROTECT`, not `R.protect`). Assuming the `R.lua` module has been loaded into a table named `R`, you can use the following R API functions: | Lua name | corresponding C signature | |--|------| | `R.allocVector` | `SEXP Rf_allocVector(SEXPTYPE type, R_xlen_t length)` | | `R.CHAR` | `const char* R_CHAR(SEXP x)` | | `R.CheckUserInterrupt` | `void R_CheckUserInterrupt(void)` | | `R.classgets` | `SEXP Rf_classgets(SEXP vec, SEXP klass)` | | `R.coerceVector` | `SEXP Rf_coerceVector(SEXP v, SEXPTYPE type)` | | `R.cons` | `SEXP Rf_cons(SEXP car, SEXP cdr)` | | `R.copyMostAttrib` | `void Rf_copyMostAttrib(SEXP inp, SEXP ans)` | | `R.DATAPTR_RO` | `const void* DATAPTR_RO(SEXP x)` | | `R.defineVar` | `void Rf_defineVar(SEXP symbol, SEXP value, SEXP rho)` | | `R.dimgets` | `SEXP Rf_dimgets(SEXP vec, SEXP val)` | | `R.dimnamesgets` | `SEXP Rf_dimnamesgets(SEXP vec, SEXP val)` | | `R.duplicate` | `SEXP Rf_duplicate(SEXP s)` | | `R.DUPLICATE_ATTRIB` | `void DUPLICATE_ATTRIB(SEXP to, SEXP from)` | | `R.eval` | `SEXP Rf_eval(SEXP e, SEXP rho)` | | `R.ExternalPtrAddr` | `void* R_ExternalPtrAddr(SEXP s)` | | `R.findFun` | `SEXP Rf_findFun(SEXP symbol, SEXP rho)` | | `R.FlushConsole` | `void R_FlushConsole(void)` | | `R.getAttrib` | `SEXP Rf_getAttrib(SEXP vec, SEXP name)` | | `R.GetOption1` | `SEXP Rf_GetOption1(SEXP tag)` | | `R.getRegisteredNamespace`\* | `SEXP R_getRegisteredNamespace(const char* name)` added in 4.6.0 | | `R.getVarEx`\* | `SEXP R_getVarEx(SEXP sym, SEXP rho, Rboolean inherits, SEXP ifnotfound)` added in 4.5.0 | | `R.inherits` | `Rboolean Rf_inherits(SEXP s, const char* name)` | | `R.install` | `SEXP Rf_install(const char* name)` | | `R.INTEGER` | `int* INTEGER(SEXP x)` | | `R.isObject` | `Rboolean Rf_isObject(SEXP s)` | | `R.lcons` | `SEXP Rf_lcons(SEXP car, SEXP cdr)` | | `R.LOGICAL` | `int* LOGICAL(SEXP x)` | | `R.lsInternal3` | `SEXP R_lsInternal3(SEXP env, Rboolean all, Rboolean sorted)` | | `R.MakeExternalPtr` | `SEXP R_MakeExternalPtr(void *p, SEXP tag, SEXP prot)` | | `R.mkChar` | `SEXP Rf_mkChar(const char* name)` | | `R.mkCharLen` | `SEXP Rf_mkCharLen(const char* name, int len)` | | `R.namesgets` | `SEXP Rf_namesgets(SEXP vec, SEXP val)` | | `R.NewEnv`\* | `SEXP R_NewEnv(SEXP enclos, int hash, int size)` added in 4.1.0 | | `R.ParentEnv`\* | `SEXP R_ParentEnv(SEXP x)` added in 4.5.0 | | `R.PreserveObject` | `void R_PreserveObject(SEXP object)` | | `R.PrintValue` | `void Rf_PrintValue(SEXP s)` | | `R.PROTECT` | `SEXP Rf_protect(SEXP s)` | | `R.RAW` | `Rbyte* RAW(SEXP x)` | | `R.ReadConsole` | `int R_ReadConsole(const char* prompt, unsigned char* buf, int buflen, int hist)` | | `R.REAL` | `double* REAL(SEXP x)` | | `R.ReleaseObject` | `void R_ReleaseObject(SEXP object)` | | `R.removeVarFromFrame` | `void R_removeVarFromFrame(SEXP name, SEXP env)` | | `R.ScalarInteger` | `SEXP Rf_ScalarInteger(int x)` | | `R.ScalarLogical` | `SEXP Rf_ScalarLogical(int x)` | | `R.ScalarReal` | `SEXP Rf_ScalarReal(double x)` | | `R.ScalarString` | `SEXP Rf_ScalarString(SEXP x)` | | `R.SET_STRING_ELT` | `void SET_STRING_ELT(SEXP x, R_xlen_t i, SEXP v)` | | `R.SET_TAG` | `void SET_TAG(SEXP x, SEXP y)` | | `R.SET_VECTOR_ELT` | `SEXP SET_VECTOR_ELT(SEXP x, R_xlen_t i, SEXP v)` | | `R.setAttrib` | `SEXP Rf_setAttrib(SEXP vec, SEXP name, SEXP val)` | | `R.SHALLOW_DUPLICATE_ATTRIB` | `void SHALLOW_DUPLICATE_ATTRIB(SEXP to, SEXP from)` | | `R.STRING_ELT` | `SEXP STRING_ELT(SEXP x, R_xlen_t i)` | | `R.STRING_PTR_RO` | `const SEXP* STRING_PTR_RO(SEXP x)` | | `R.TAG` | `SEXP TAG(SEXP e)` | | `R.type2char` | `const char* Rf_type2char(SEXPTYPE t)` | | `R.TYPEOF` | `int TYPEOF(SEXP x)` | | `R.UNPROTECT` | `void Rf_unprotect(int l)` | | `R.VECTOR_ELT` | `SEXP VECTOR_ELT(SEXP x, R_xlen_t i)` | \* Entries marked with an asterisk were not present in R 4.0.0 (the minimum R version that **luajr** supports), but were added in later versions (as described in the table). However, they will work with any version of R (from 4.0.0 onward) because **luajr** implements backwards-compatible versions of these functions. In addition to the functions above, the `R.lua` module provides some convenience functions to wrap some helpful operations. **`R.length(x)`** Returns the length of `SEXP x` as a Lua number. This is a wrapper for `Rf_xlength()` that converts the result from R's 64-bit length type to a Lua number. You can use this anywhere you would normally use `Rf_length()` or `Rf_xlength()` in C. **`R.type_string(x)`** Returns the SEXP type of `SEXP x` as a Lua string. This is a wrapper for `Rf_type2char(TYPEOF(x))`. **`R.set_parent(env, parent)`** Sets the parent environment of `SEXP env`, an `ENVSXP`, to the `ENVSXP` `parent`. This calls into R's `parent.env<-` function because the R C API does not currently provide a setter for environment parents. ## Constants Common R constants are exposed as follows: | Lua name | C source | |--|------| | `R.TRUE` | `1` | | `R.FALSE` | `0` | | `R.NilValue` | `R_NilValue` | | `R.NA_LOGICAL` | `R_NaInt` | | `R.NA_INTEGER` | `R_NaInt` | | `R.NA_REAL` | `R_NaReal` | | `R.NA_STRING` | `R_NaString` | | `R.UnboundValue` | `R_UnboundValue` | | `R.MissingArg` | `R_MissingArg` | | `R.GlobalEnv` | `R_GlobalEnv` | | `R.EmptyEnv` | `R_EmptyEnv` | | `R.BaseEnv` | `R_BaseEnv` | | `R.BlankString` | `R_BlankString` | | `R.NamesSymbol` | `R_NamesSymbol` | | `R.ClassSymbol` | `R_ClassSymbol` | | `R.DimSymbol` | `R_DimSymbol` | | `R.DimNamesSymbol` | `R_DimNamesSymbol` | | `R.RowNamesSymbol` | `R_RowNamesSymbol` | | `R.NamespaceRegistry` | `R_NamespaceRegistry` | In addition to the above, there is also a variable `R.version` that holds the current R version as an integer in the form `MMmmpp` (MM = major, mm = minor, pp = patch). For example, R 4.6.0 is `040600` and R 4.0.5 is `040005`. The R type codes (`SEXPTYPE`s) are also exposed as Lua numbers. These correspond to the values returned by `R.TYPEOF(x)`: | Lua name | Value | Description | |--|--|------| | `R.NILSXP` | 0 | NULL | | `R.SYMSXP` | 1 | symbols | | `R.LISTSXP` | 2 | pairlists | | `R.CLOSXP` | 3 | closures | | `R.ENVSXP` | 4 | environments | | `R.PROMSXP` | 5 | promises | | `R.LANGSXP` | 6 | language objects | | `R.SPECIALSXP` | 7 | special functions | | `R.BUILTINSXP` | 8 | builtin functions | | `R.CHARSXP` | 9 | internal character strings | | `R.LGLSXP` | 10 | logical vectors | | `R.INTSXP` | 13 | integer vectors | | `R.REALSXP` | 14 | numeric vectors | | `R.CPLXSXP` | 15 | complex vectors | | `R.STRSXP` | 16 | character vectors | | `R.DOTSXP` | 17 | dot-dot-dot object | | `R.ANYSXP` | 18 | make "any" args work | | `R.VECSXP` | 19 | list (generic vector) | | `R.EXPRSXP` | 20 | expression vector | | `R.BCODESXP` | 21 | byte code | | `R.EXTPTRSXP` | 22 | external pointer | | `R.WEAKREFSXP` | 23 | weak reference | | `R.RAWSXP` | 24 | raw vector | | `R.OBJSXP` | 25 | objects not of simple type | If all of this makes sense to you, then enjoy and happy coding. If not, then stick to using [the luajr.lua module](luajr-module.html) and don't worry about it too much -- you probably don't need this anyway!