@@ -109,27 +109,56 @@ void interpreter::configure_impl()
109
109
r::invoke_xeusr_fn (" configure" );
110
110
}
111
111
112
- nl::json interpreter::is_complete_request_impl (const std::string& code )
112
+ nl::json interpreter::is_complete_request_impl (const std::string& code_ )
113
113
{
114
- SEXP s_code = PROTECT (Rf_mkString (code.c_str ()));
115
- ParseStatus status;
116
-
117
- // Currently ignore the result of R_ParseVector, and only care about status
118
- R_ParseVector (s_code, -1 , &status, R_NilValue);
119
- UNPROTECT (1 ); // s_code
120
-
121
- switch (status) {
122
- case PARSE_EOF:
123
- case PARSE_NULL:
124
- case PARSE_OK:
125
- return xeus::create_is_complete_reply (" complete" , " " );
126
-
127
- case PARSE_INCOMPLETE:
128
- return xeus::create_is_complete_reply (" incomplete" , " " );
114
+ // initially code holds the string, but then it is being
115
+ // replaced by incomplete, invalid or complete either in the
116
+ // body handler or the error handler
117
+ SEXP code = PROTECT (Rf_mkString (code_.c_str ()));
118
+
119
+ // we can't simply use an R callback because the R parse(text =)
120
+ // approach does not distinguish between invalid code and
121
+ // incomplete: they both just throw an error
122
+ R_tryCatchError (
123
+ [](void * void_code) { // body
124
+ ParseStatus status;
125
+ SEXP code = reinterpret_cast <SEXP>(void_code);
126
+
127
+ R_ParseVector (code, -1 , &status, R_NilValue);
128
+
129
+ switch (status) {
130
+ case PARSE_INCOMPLETE:
131
+ SET_STRING_ELT (code, 0 , Rf_mkChar (" incomplete" ));
132
+ break ;
133
+
134
+ case PARSE_ERROR:
135
+ SET_STRING_ELT (code, 0 , Rf_mkChar (" invalid" ));
136
+ break ;
137
+
138
+ default :
139
+ SET_STRING_ELT (code, 0 , Rf_mkChar (" complete" ));
140
+ }
141
+
142
+ return R_NilValue;
143
+ },
144
+ reinterpret_cast <void *>(code),
145
+
146
+ [](SEXP, void * void_code) { // handler
147
+ // some parse error cases are not propagated to PARSE_ERROR
148
+ // but rather throw an error, so we need to catch it
149
+ // and set the result to invalid
150
+ SEXP code = reinterpret_cast <SEXP>(void_code);
151
+ SET_STRING_ELT (code, 0 , Rf_mkChar (" invalid" ));
152
+
153
+ return R_NilValue;
154
+ },
155
+ reinterpret_cast <void *>(code)
156
+ );
129
157
130
- case PARSE_ERROR:
131
- return xeus::create_is_complete_reply (" invalid" , " " );
132
- }
158
+ // eventually we just have to extract the string from code (which has been replaced)
159
+ auto result = xeus::create_is_complete_reply (CHAR (STRING_ELT (code, 0 )), " " );
160
+ UNPROTECT (1 );
161
+ return result;
133
162
}
134
163
135
164
nl::json interpreter::complete_request_impl (const std::string& code,
0 commit comments