Skip to content

Commit

Permalink
Rtcl 1.1 update release adds -verbose switch to all Rtcl commands.
Browse files Browse the repository at this point in the history
This update adds optional -verbose switch to all Rtcl
commands. Presence of -verbose causes embedded R interpreter to print
the results of R expressions to stdout as they are evaluated. This may
be used to debug the results of R expressons as Rtcl commands are run
(see Rtcl man page). This was the default in 1.0 however R's stdout
messages are not used by Rtcl and caused excessive output to stdout.

Based on patch and suggestion provided by Dr. Luc Moulinier
<luc.moulinier@unistra.fr>.

Changes include:

- New optional -verbose switch to all Rtcl commands

- Updated man page and README

Signed-off-by: Matt Adams <matt.adams@radicaldynamic.com>
  • Loading branch information
mattadams committed May 14, 2018
1 parent 01909d6 commit 01a1414
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 33 deletions.
14 changes: 14 additions & 0 deletions ChangeLog
@@ -1,3 +1,17 @@
2018-05-13 Matt Adams <matt.adams@stuffbymatt.ca>

* rtcl.c: New Rtcl 1.1 version adds optional -verbose switch to
all Rtcl commands. Presence of -verbose causes embedded R
interpreter to print the results of R expressions to stdout as
they are evaluated. This may be used to debug the results of R
expressions as Rtcl commands are run. This was the default in 1.0
however it causes huge log files. Change based on patch and
suggestion provided by Luc Moulinier <luc.moulinier@unistra.fr>.

* doc/Rtcl.n: Updated nroff man page for -verbose switch

* doc/Rtcl.tmml: Updated doctools man page for -verbose switch

2018-04-13 Matt Adams <matt.adams@radicaldynamic.com>

* rtcl.c: New Rtcl 1.0 version compatible with Tcl 8.6.8 and R
Expand Down
14 changes: 13 additions & 1 deletion README
Expand Up @@ -70,6 +70,16 @@ If this happens to you follow the instructions in "FreeBSD Notes" to
resolve the error.


KNOWN TO WORK ON
================

- FreeBSD 11.1 with Tcl 8.6.8 and R 3.4.4
Reported by Matt Adams

- Ubuntu 14.4 LTS with Tcl 8.6.7 and R 3.4.4
Reported by Luc Moulinier


FREEBSD NOTES
=============

Expand Down Expand Up @@ -143,4 +153,6 @@ HISTORY

Versions 0.1 through 0.3 were initially developed and released by Neil
McKay on Redhat Linux 8. Versions 1.0 and later were revised and
packaged by Matt Adams on FreeBSD 11.
packaged by Matt Adams on FreeBSD 11.

See ChangeLog for detailed notes.
51 changes: 43 additions & 8 deletions doc/Rtcl.n
Expand Up @@ -279,13 +279,13 @@ package require \fBTcl 8\&.6\fR
.sp
package require \fBRtcl 1\&.0\fR
.sp
\fB::rtcl::eval\fR \fIR Expression\fR
\fB::rtcl::eval\fR \fI?-verbose?\fR \fIR Expression\fR
.sp
\fB::rtcl::source\fR \fI/path/to/foo\&.R\fR
\fB::rtcl::source\fR \fI?-verbose?\fR \fI/path/to/foo\&.R\fR
.sp
\fB::rtcl::gettype\fR \fIR Expression\fR
\fB::rtcl::gettype\fR \fI?-verbose?\fR \fIR Expression\fR
.sp
\fB::rtcl::getvalue\fR \fIR Expression\fR
\fB::rtcl::getvalue\fR \fI?-verbose?\fR \fIR Expression\fR
.sp
.BE
.SH DESCRIPTION
Expand All @@ -299,27 +299,62 @@ Due to the potential for errors, it is recommended that you wrap all
Rtcl routines with \fBcatch\fR or \fBtry\fR\&.
.SH COMMANDS
.TP
\fB::rtcl::eval\fR \fIR Expression\fR
\fB::rtcl::eval\fR \fI?-verbose?\fR \fIR Expression\fR
Evaluates an \fIR Expression\fR inside the embedded R interpreter\&.
Returns an error message if the expression cannot be parsed or
evaluated\&. Returns nothing if successful\&.
.sp
If \fI-verbose\fR (optional) is present, the R interpreter will print
the results of R expressions to stdout as they are evaluated\&. This may
be used to debug the results of R expressions as Rtcl commands are
run\&. For example:
.CS

$ tclsh
% package require Rtcl
1\&.0
% ::rtcl::eval {x <- 1+1}
% ::rtcl::getvalue {x}
2\&.0
% ::rtcl::eval -verbose {x <- 1+1}
[1] 2
% ::rtcl::getvalue {x}
2\&.0
%

.CE
.TP
\fB::rtcl::source\fR \fI/path/to/foo\&.R\fR
\fB::rtcl::source\fR \fI?-verbose?\fR \fI/path/to/foo\&.R\fR
Sources a file into the embedded R interpreter\&. Takes a single
argument that must be the fully qualified path to a valid R
file\&. Returns an error message if the file cannot be found or properly
parsed, and returns nothing if successful\&.
.sp
If \fI-verbose\fR (optional) is present, the R interpreter will print
the results of R expressions to stdout as they are evaluated\&. This may
be used to debug the results of R expressions as Rtcl commands are
run\&.
.TP
\fB::rtcl::gettype\fR \fIR Expression\fR
\fB::rtcl::gettype\fR \fI?-verbose?\fR \fIR Expression\fR
Evaluates an \fIR Expression\fR inside the embedded R interpreter\&.
Returns an error if the expression cannot be parsed or evaluated\&.
Otherwise, it returns the R data type of the result\&.
.sp
If \fI-verbose\fR (optional) is present, the R interpreter will print
the results of R expressions to stdout as they are evaluated\&. This may
be used to debug the results of R expressions as Rtcl commands are
run\&.
.TP
\fB::rtcl::getvalue\fR \fIR Expression\fR
\fB::rtcl::getvalue\fR \fI?-verbose?\fR \fIR Expression\fR
Evaluates an \fIR Expression\fR inside the embedded R interpreter\&.
Returns an error if the expression cannot be parsed or evaluated\&. It
then tries to convert the returned value to a Tcl equivalent\&. If it
can, it returns the value; otherwise, it returns an error\&.
.sp
If \fI-verbose\fR (optional) is present, the R interpreter will print
the results of R expressions to stdout as they are evaluated\&. This may
be used to debug the results of R expressions as Rtcl commands are
run\&.
.PP
.SH FREEBSD
On FreeBSD there is a long standing issue with libgcc_s\&.so in base
Expand Down
49 changes: 45 additions & 4 deletions doc/Rtcl.tmml
Expand Up @@ -26,32 +26,73 @@ Rtcl routines with [cmd catch] or [cmd try].

[list_begin definitions]

[call [cmd ::rtcl::eval] [arg {R Expression}]]
[call [cmd ::rtcl::eval] [arg ?-verbose?] [arg {R Expression}]]

Evaluates an [arg {R Expression}] inside the embedded R interpreter.
Returns an error message if the expression cannot be parsed or
evaluated. Returns nothing if successful.

[call [cmd ::rtcl::source] [arg /path/to/foo.R]]
[para]

If [arg -verbose] (optional) is present, the R interpreter will print
the results of R expressions to stdout as they are evaluated. This may
be used to debug the results of R expressions as Rtcl commands are
run. For example:

[example_begin]$ tclsh
% package require Rtcl
1.0
% ::rtcl::eval {x <- 1+1}
% ::rtcl::getvalue {x}
2.0
% ::rtcl::eval -verbose {x <- 1+1}
[lb]1[rb] 2
% ::rtcl::getvalue {x}
2.0
%
[example_end]

[call [cmd ::rtcl::source] [arg ?-verbose?] [arg /path/to/foo.R]]

Sources a file into the embedded R interpreter. Takes a single
argument that must be the fully qualified path to a valid R
file. Returns an error message if the file cannot be found or properly
parsed, and returns nothing if successful.

[call [cmd ::rtcl::gettype] [arg {R Expression}]]
[para]

If [arg -verbose] (optional) is present, the R interpreter will print
the results of R expressions to stdout as they are evaluated. This may
be used to debug the results of R expressions as Rtcl commands are
run.

[call [cmd ::rtcl::gettype] [arg ?-verbose?] [arg {R Expression}]]

Evaluates an [arg {R Expression}] inside the embedded R interpreter.
Returns an error if the expression cannot be parsed or evaluated.
Otherwise, it returns the R data type of the result.

[call [cmd ::rtcl::getvalue] [arg {R Expression}]]
[para]

If [arg -verbose] (optional) is present, the R interpreter will print
the results of R expressions to stdout as they are evaluated. This may
be used to debug the results of R expressions as Rtcl commands are
run.

[call [cmd ::rtcl::getvalue] [arg ?-verbose?] [arg {R Expression}]]

Evaluates an [arg {R Expression}] inside the embedded R interpreter.
Returns an error if the expression cannot be parsed or evaluated. It
then tries to convert the returned value to a Tcl equivalent. If it
can, it returns the value; otherwise, it returns an error.

[para]

If [arg -verbose] (optional) is present, the R interpreter will print
the results of R expressions to stdout as they are evaluated. This may
be used to debug the results of R expressions as Rtcl commands are
run.

[list_end]

[section FREEBSD]
Expand Down
68 changes: 48 additions & 20 deletions generic/rtcl.c
@@ -1,5 +1,5 @@
/*
* hello.c -- A minimal Tcl C extension.
* rtcl.c -- A minimal Tcl C extension for embedded R
*/
#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -179,7 +179,7 @@ RtoTcl(interp, retObjPtrPtr, s)
} else if (l == 1) {
return(RtoTcl(interp, retObjPtrPtr, CAR(s)));
} else {
objv = (Tcl_Obj **) Tcl_Alloc(l*sizeof(Tcl_Obj *));
objv = (Tcl_Obj **) Tcl_Alloc(l * sizeof(Tcl_Obj *));

for (i = 0; s != NULL && s != R_NilValue; i++, s = CDR(s)) {
RtoTcl(interp, &(objv[i]), CAR(s));
Expand Down Expand Up @@ -368,20 +368,32 @@ REval(interp, s, objc, objv)
Tcl_Interp *interp; /* For error messages */
SEXP *s; /* S-Expression to put result in */
int objc; /* Number of arguments */
Tcl_Obj *CONST objv[]; /* Arguments */
Tcl_Obj *CONST objv[]; /* Arguments */
{
int i, l, evalError;
ParseStatus status;
SEXP text;
SEXP exp, val;
SEXP geterr, err;
char *errmsg;
int offset, verbose;

/* Check for verbose option */
if (strcmp(Tcl_GetString(objv[1]),"-verbose") == 0) {
offset = 2;
verbose = 1;
objc -= 2;
} else {
offset = 1;
verbose = 0;
objc--;
}

/* Get the exp to evaluate */
text = PROTECT(allocVector(STRSXP, objc));

for (i = 0; i < objc; i++ ) {
SET_STRING_ELT(text, i, mkChar(Tcl_GetString(objv[i])));
SET_STRING_ELT(text, i, mkChar(Tcl_GetString(objv[i+offset])));
}

/* Parse it */
Expand Down Expand Up @@ -410,7 +422,9 @@ REval(interp, s, objc, objv)

return TCL_ERROR;
} else {
PrintValue(val);
if (verbose) {
PrintValue(val);
}
}

l = length(exp);
Expand Down Expand Up @@ -444,17 +458,17 @@ Rtcl_eval(clientData, interp, objc, objv)
ClientData clientData; /* Not used. */
Tcl_Interp *interp; /* Current interpreter */
int objc; /* Number of arguments */
Tcl_Obj *CONST objv[]; /* Arguments */
Tcl_Obj *CONST objv[]; /* Arguments */
{
SEXP ans;

if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "{R Expression}");
Tcl_WrongNumArgs(interp, 1, objv, "?-verbose? {R Expression}");
return TCL_ERROR;
}

/* Evaluate the args */
if (REval(interp, &ans, objc - 1, &(objv[1])) != TCL_OK) {
if (REval(interp, &ans, objc, objv) != TCL_OK) {
return TCL_ERROR;
}

Expand Down Expand Up @@ -489,13 +503,25 @@ Rtcl_source(clientData, interp, objc, objv)
SEXP exp, val;
SEXP geterr, err;
char *errmsg;
int offset, verbose;

if (objc > 2) {
Tcl_WrongNumArgs(interp, 1, objv, "{source_file.R}");
Tcl_WrongNumArgs(interp, 1, objv, "?-verbose? {source_file.R}");
return TCL_ERROR;
}

PROTECT(exp = lang2(install("source"), mkString(Tcl_GetString(objv[1]))));
/* Check for verbose option */
if (strcmp(Tcl_GetString(objv[1]),"-verbose") == 0) {
offset = 2;
verbose = 1;
objc -= 2;
} else {
offset = 1;
verbose = 0;
objc--;
}

PROTECT(exp = lang2(install("source"), mkString(Tcl_GetString(objv[offset]))));
val = R_tryEval(exp, R_GlobalEnv, &evalError);

if (evalError) {
Expand All @@ -512,7 +538,9 @@ Rtcl_source(clientData, interp, objc, objv)

return TCL_ERROR;
} else {
PrintValue(val);
if (verbose) {
PrintValue(val);
}
}

UNPROTECT(1);
Expand Down Expand Up @@ -546,12 +574,12 @@ Rtcl_gettype(clientData, interp, objc, objv)
Tcl_Obj *r;

if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "{R_expression ...}");
Tcl_WrongNumArgs(interp, 1, objv, "?-verbose? {R_expression ...}");
return TCL_ERROR;
}

/* Evaluate the args */
if (REval(interp, &ans, objc - 1, &(objv[1])) != TCL_OK) {
if (REval(interp, &ans, objc, objv) != TCL_OK) {
return TCL_ERROR;
}

Expand Down Expand Up @@ -592,18 +620,18 @@ Rtcl_getvalue(clientData, interp, objc, objv)
ClientData clientData; /* Not used. */
Tcl_Interp *interp; /* Current interpreter */
int objc; /* Number of arguments */
Tcl_Obj *CONST objv[]; /* Arguments */
Tcl_Obj *CONST objv[]; /* Arguments */
{
SEXP ans;
Tcl_Obj *r;

if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "{R Expression}");
Tcl_WrongNumArgs(interp, 1, objv, "?-verbose? {R Expression}");
return TCL_ERROR;
}

/* Evaluate the args */
if (REval(interp, &ans, objc - 1, &(objv[1])) != TCL_OK) {
if (REval(interp, &ans, objc, objv) != TCL_OK) {
return TCL_ERROR;
}

Expand Down Expand Up @@ -667,16 +695,16 @@ int DLLEXPORT Rtcl_Init(Tcl_Interp *interp)
return TCL_ERROR;
}

Tcl_CreateObjCommand(interp, "::rtcl::eval", Rtcl_eval,
Tcl_CreateObjCommand(interp, "::rtcl::eval", (Tcl_ObjCmdProc *) Rtcl_eval,
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

Tcl_CreateObjCommand(interp, "::rtcl::source", Rtcl_source,
Tcl_CreateObjCommand(interp, "::rtcl::source", (Tcl_ObjCmdProc *) Rtcl_source,
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

Tcl_CreateObjCommand(interp, "::rtcl::gettype", Rtcl_gettype,
Tcl_CreateObjCommand(interp, "::rtcl::gettype", (Tcl_ObjCmdProc *) Rtcl_gettype,
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

Tcl_CreateObjCommand(interp, "::rtcl::getvalue", Rtcl_getvalue,
Tcl_CreateObjCommand(interp, "::rtcl::getvalue", (Tcl_ObjCmdProc *) Rtcl_getvalue,
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

return TCL_OK;
Expand Down

0 comments on commit 01a1414

Please sign in to comment.