This repository has been archived by the owner on Feb 22, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlibR.mjs
259 lines (243 loc) · 9.84 KB
/
libR.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
"use strict";
import child_process from "child_process";
import process from "process";
import path from "path";
import ffi from "ffi";
import ref from "ref";
import refArray from "ref-array";
import refStruct from "ref-struct";
import { default as windowsRegistry } from "./safe-windows-registry.js";
import debug_ from "debug";
const debug = debug_("libr-bridge:libR");
/* Type */
const stringArr = refArray(ref.types.CString); // char * [] or string[]
export const SEXP = ref.refType(ref.types.void);
export const SEXPREC_ALIGN_SIZE = ref.types.double.size;
export const ComplexInR = refStruct({
r: ref.types.double,
i: ref.types.double
});
/** R SEXP type enums */
export const SEXPTYPE = {
NILSXP : 0, /* nil : NULL */
SYMSXP : 1, /* symbols */
LISTSXP : 2, /* lists of dotted pairs */
CLOSXP : 3, /* closures */
ENVSXP : 4, /* environments */
PROMSXP : 5, /* promises: [un]evaluated closure arguments */
LANGSXP : 6, /* language constructs (special lists) */
SPECIALSXP : 7, /* special forms */
BUILTINSXP : 8, /* builtin non-special forms */
CHARSXP : 9, /* "scalar" string type (internal only)*/
LGLSXP : 10, /* logical vectors */
INTSXP : 13, /* integer vectors */
REALSXP : 14, /* real variables */
CPLXSXP : 15, /* complex variables */
STRSXP : 16, /* string vectors */
DOTSXP : 17, /* dot-dot-dot object */
ANYSXP : 18, /* make "any" args work */
VECSXP : 19, /* generic vectors */
EXPRSXP : 20, /* expressions vectors */
BCODESXP : 21, /* byte code */
EXTPTRSXP : 22, /* external pointer */
WEAKREFSXP : 23, /* weak reference */
RAWSXP : 24, /* raw bytes */
S4SXP : 25, /* S4 non-vector */
NEWSXP : 30, /* fresh node creaed in new page */
FREESXP : 31, /* node released by GC */
FUNSXP : 99 /* Closure or Builtin */
};
export const ParseStatus = {
PARSE_NULL: 0,
PARSE_OK: 1,
PARSE_INCOMPLETE: 2,
PARSE_ERROR: 3,
PARSE_EOF: 4
};
export const cetype_t = {
CE_NATIVE : 0,
CE_UTF8 : 1,
CE_LATIN1 : 2,
CE_BYTES : 3,
CE_SYMBOL : 5,
CE_ANY : 99
};
const apiList = {
"CAR": [SEXP, [SEXP]],
"CDR": [SEXP, [SEXP]],
"NAMED": ["int", [SEXP]],
"R_CHAR": ["string", [SEXP]],
"R_curErrorBuf": ["string", []],
"R_NilValue": [SEXP, []],
// "R_ParseEvalString": [SEXP, ["string", SEXP]], - I don't know why, but Windows dll doesn't have this function.
"R_ParseVector": [SEXP, [SEXP, "int", "int*", SEXP]], // SEXP R_ParseVector(SEXP text, int n, ParseStatus *status, SEXP srcfile)
"R_PreserveObject": ["void", [SEXP]],
"R_ReleaseObject": ["void", [SEXP]],
"R_setStartTime": ["void", []], // void R_setStartTime(void);
// "R_sysframe": [SEXP, ["int", "pointer"]],
"R_tryEval": [SEXP, [SEXP, SEXP, "int*"]], // SEXP R_tryEval(SEXP e, SEXP env, int *ErrorOccurred)
"R_tryEvalSilent": [SEXP, [SEXP, SEXP, "int*"]], // SEXP R_tryEvalSilent(SEXP e, SEXP env, int *ErrorOccurred)
"Rf_GetRowNames": [SEXP, [SEXP]],
"Rf_ScalarInteger": [SEXP, ["int"]],
"Rf_ScalarLogical": [SEXP, ["int"]],
"Rf_ScalarReal": [SEXP, ["double"]], // SEXP ScalarReal(double x)
"Rf_allocVector": [SEXP, ["int", "int"]], // SEXP Rf_allocVector(SEXPTYPE, int R_xlen_t);
"Rf_asChar": [SEXP, [SEXP]],
"Rf_asInteger": ["int", [SEXP]],
"Rf_asLogical": ["int", [SEXP]],
"Rf_asReal": ["double", [SEXP]],
"Rf_cons": [SEXP, [SEXP, SEXP]],
"Rf_defineVar": ["void", [SEXP, SEXP, "pointer"]],
"Rf_elt": [SEXP, [SEXP, "int"]],
"Rf_endEmbeddedR": ["void", ["int"]], // void Rf_endEmbeddedR(int fatal);
"Rf_eval": [SEXP, [SEXP, "int*"]],
"Rf_findFun": [SEXP, [SEXP, SEXP]], // SEXP Rf_findFun(SEXP, SEXP)
"Rf_findVar": [SEXP, [SEXP, SEXP]], // SEXP Rf_findVar(SEXP, SEXP)
"Rf_getAttrib": [SEXP, [SEXP, SEXP]],
"Rf_initEmbeddedR": ["int", ["int", stringArr]], // int Rf_initEmbeddedR(int argc, char *argv[]);
"Rf_initialize_R": ["int", ["int", stringArr]],
"Rf_install": [SEXP, ["string"]],
"Rf_isArray": ["int", [SEXP]], // Rboolean Rf_isArray(SEXP);
"Rf_isComplex": ["int", [SEXP]], // Rboolean Rf_isComplex(SEXP);
"Rf_isExpression": ["int", [SEXP]], // Rboolean Rf_isExpression(SEXP);
"Rf_isFactor": ["int", [SEXP]], // Rboolean Rf_isFactor(SEXP);
"Rf_isFunction": ["int", [SEXP]], // Rboolean Rf_isFunction(SEXP);
"Rf_isInteger": ["int", [SEXP]], // Rboolean Rf_isInteger(SEXP);
"Rf_isList": ["int", [SEXP]], // Rboolean Rf_isList(SEXP);
"Rf_isLogical": ["int", [SEXP]], // Rboolean Rf_isLogical(SEXP);
"Rf_isMatrix": ["int", [SEXP]], // Rboolean Rf_isMatrix(SEXP);
"Rf_isNull": ["int", [SEXP]], // Rboolean Rf_isNull(SEXP);
"Rf_isNumber": ["int", [SEXP]], // Rboolean Rf_isNumber(SEXP);
"Rf_isNumeric": ["int", [SEXP]], // Rboolean Rf_isNumeric(SEXP);
"Rf_isPrimitive": ["int", [SEXP]], // Rboolean Rf_isPrimitive(SEXP);
"Rf_isReal": ["int", [SEXP]], // Rboolean Rf_isReal(SEXP);
"Rf_isS4": ["int", [SEXP]], // Rboolean Rf_isS4(SEXP);
"Rf_isString": ["int", [SEXP]], // Rboolean Rf_isString(SEXP);
"Rf_isValidString": ["int", [SEXP]], // Rboolean Rf_isValidString(SEXP);
"Rf_isVector": ["int", [SEXP]], // Rboolean Rf_isVector(SEXP);
"Rf_isFrame": ["int", [SEXP]], // Rboolean Rf_isFrame(SEXP);
"Rf_isSymbol": ["int", [SEXP]], // Rboolean Rf_isSymbol(SEXP);
"Rf_lang1": [SEXP, [SEXP]],
"Rf_lang2": [SEXP, [SEXP, SEXP]],
"Rf_lang3": [SEXP, [SEXP, SEXP, SEXP]],
"Rf_lang4": [SEXP, [SEXP, SEXP, SEXP, SEXP]],
"Rf_lang5": [SEXP, [SEXP, SEXP, SEXP, SEXP, SEXP]],
"Rf_lang6": [SEXP, [SEXP, SEXP, SEXP, SEXP, SEXP, SEXP]],
"Rf_lcons": [SEXP, [SEXP, SEXP]],
"Rf_length": ["int", [SEXP]],
"Rf_lengthgets": [SEXP, [SEXP]],
"Rf_mainloop": ["void", []], // void Rf_mainloop();
"Rf_mkChar": [SEXP, ["string"]],
"Rf_mkCharCE": [SEXP, ["string", "int"]],
"Rf_mkString": [SEXP, ["string"]],
"Rf_protect": [SEXP, [SEXP]],
"Rf_setAttrib": [SEXP, [SEXP, SEXP, SEXP]],
"Rf_setVar": [SEXP, [SEXP, SEXP, SEXP]],
"Rf_translateCharUTF8": ["string", [SEXP]], // const char* Rf_translateCharUTF8(SEXP x)
"Rf_unprotect": ["void", ["int"]],
"SET_NAMED": ["void", [SEXP, "int"]],
"SET_STRING_ELT": [SEXP, [SEXP, "int", SEXP]], // memory.c
"SET_TAG": ["void", [SEXP, SEXP]],
"STRING_ELT": [SEXP, [SEXP, "int"]], // memory.c
"STRING_PTR": ["pointer", [SEXP]], // memory.c
"ALTVEC_DATAPTR": ["pointer", [SEXP]],
"STDVEC_DATAPTR": ["pointer", [SEXP]],
"DATAPTR": ["pointer", [SEXP]],
"TAG": [SEXP, [SEXP]],
"TYPEOF": ["int", [SEXP]],
"VECTOR_ELT": [SEXP, [SEXP, "int"]],
"ptr_R_Busy": ["pointer", undefined], // void R_Busy (int which)
"ptr_R_ShowMessage": ["pointer", undefined], // void R_ShowMessage(const char *s)
"ptr_R_ReadConsole": ["pointer", undefined], // int R_ReadConsole(const char *prompt, unsigned char *buf, int len, int addtohistory);
"ptr_R_WriteConsole": ["pointer", undefined], // void R_WriteConsole(const char *buf, int len)
"ptr_R_WriteConsoleEx": ["pointer", undefined], // void R_WriteConsoleEx(const char *buf, int len, int otype)
"R_GlobalEnv": [SEXP, undefined],
"R_NaString": [SEXP, undefined],
"R_BlankString": [SEXP, undefined],
//"R_IsNA": ["int", [ieee_double]], // Rboolean R_IsNA(double);
//"R_IsNaN": ["int", [ieee_double]], // Rboolean R_IsNaN(double);
};
var libR = undefined;
/**
* Load libR from appropriate place.
* @constructor
* @param r_path "auto" (default) || "environment" || "system" || "buildin" || path to R_HOME
* "auto" - try "environment" -> "system" -> "buildin"
* "environment" - use environmental R_HOME and LD_LIBRARY_PATH. libr-bridge handles nothing.
* "system" - find system installed R
* "buildin" - (NOT IMPLEMENTED) use redistributed binary attached with libr-bridge-bin
* @returns libR object which enables access to dynamic link library.
*/
export default function createLibR(r_path = "auto"){
if(libR !== void 0){
return libR;
}
debug(`creating libR: ${r_path}`);
if(r_path == "auto"){
try{
libR = createLibR("environment");
}catch(e){
try{
libR = createLibR("system");
}catch(e){
try{
libR = createLibR("buildin");
}catch(e){
throw new Error("R not found. Please specify path manually.");
}
}
}
}else if(r_path == "environment"){
// use environmental R_HOME
if(process.env.R_HOME !== void 0){
libR = createLibR(process.env.R_HOME);
}
}else if(r_path == "system"){
let my_path;
try {
if (process.platform == "win32") {
const windef = windowsRegistry.windef;
let k;
try {
k = new windowsRegistry.Key(windef.HKEY.HKEY_LOCAL_MACHINE, "SOFTWARE\\R-core\\R", windef.KEY_ACCESS.KEY_READ);
}catch(e){
debug("No key in HLM, finding HCU.");
k = new windowsRegistry.Key(windef.HKEY.HKEY_CURRENT_USER, "SOFTWARE\\R-core\\R", windef.KEY_ACCESS.KEY_READ);
}
my_path = k.getValue("InstallPath");
k.close();
}else{
const ret = child_process.execSync("Rscript -e \"cat(Sys.getenv('R_HOME'))\"");
my_path = ret.toString();
}
libR = createLibR(my_path);
}catch(e){
debug("Loading system R failure: " + e);
throw new Error("Couldn't load installed R (RScript not found or bad registry)");
}
}else if(r_path == "buildin"){
throw new Error("NOT IMPLEMENTED.");
}else if(r_path == ""){
throw new Error("Please specify installed R.");
}else{
// assuming path of installed R is specified.
const delim = path.delimiter;
if(r_path.slice(-1) == path.sep) r_path = r_path.slice(0, -1); // remove trailing "/" (or "\")
process.env.R_HOME = r_path;
if (process.platform == "win32") {
process.env.PATH = `${r_path}\\bin\\x64${delim}` + process.env.PATH;
libR = ffi.Library(`${r_path}\\bin\\x64\\R.dll`, apiList);
}else{
process.env.LD_LIBRARY_PATH = `${r_path}${delim}${r_path}/lib${delim}` + process.env.LD_LIBRARY_PATH;
process.env.DYLD_LIBRARY_PATH = `${r_path}${delim}${r_path}/lib${delim}` + process.env.DYLD_LIBRARY_PATH;
libR = ffi.Library("libR", apiList);
}
}
if(libR == undefined){
throw new Error("Couldn't read libR");
}
return libR;
}
/*
* vim: filetype=javascript
*/