-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ParseData
type
#508
Add ParseData
type
#508
Conversation
crates/harp/src/data_frame.rs
Outdated
// SAFETY: Protected by `list` | ||
let obj = RObject::view(sexp); | ||
|
||
let dim = unsafe { harp::df_dim(obj.sexp) }?; | ||
let nrow = dim.num_rows as usize; | ||
let ncol = list.obj.length() as usize; | ||
|
||
let Some(names) = obj.names() else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels kind of weird. Can you not get names()
out of a List
? That seems to be the only need for the view()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The safety note is about why we store an RObject
view in DataFrame.obj
.
I reworded a little to consistently use list.obj
and moved the view later for construction.
impl PartialEq for RObject { | ||
// FIXME: At call sites, not obvious that this is doing identity comparisons. | ||
// Can we require explicit `FOO.sexp == BAR.sexp`? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like that
0ea65fc
to
83f04fb
Compare
So it can be used in `parse_status()` which is called very early during init.
On further thought, `UnexpectedStructure` feels like a temporary API that should not be relied upon. So we might just as well use the weakly typed variant.
And move out of definition macro
And implement for references rather than owned values
And use that in `&RObject` to `Vec` conversions to transform `NULL` inputs to vectors
83f04fb
to
eba82d4
Compare
Co-authored-by: Davis Vaughan <davis@rstudio.com>
83e1d07
to
80f7d40
Compare
This new type wraps the data frame of parse information generated by the R parser when:
getOption("keep.source")
isTRUE
).getOption("keep.parse.data")
isTRUE
(the default).This parse data is interesting for the task of determining expression boundaries in a string because it is written by the parser even in the case of an incomplete or invalid input. Unfortunately there is no information about parse failures that we can use, but knowing the boundaries of valid expressions will prove very useful as it allows the following strategy:
R_ParseVector()
to figure out the boundaries of incomplete and invalid inputs in the last expression.Progress towards posit-dev/positron#1326.
This work is supported by the following infrastructure improvements that are also part of this PR:
New
DataFrame
type that validates its input. Once constructed, the following guarantees are provided:"data.frame"
classThere is a new
Error::MissingColumnError
returned fromDataFrame::col()
when an expected column is missing.New
harp::assert_class()
returns a newError::UnexpectedClass
.New
harp::unreachable!()
macro returns anError::AnyhowError
.New
.inherits()
,.class()
, and.dim()
methods forRObject
.New coercion methods from
&RObject
toVec<T>
used to validate column types. These use a generic helper. I tried to integrate this helper in theVector
trait but couldn't solve compiler errors. Alternatively we could generate them withvector_macros
but unless it saves a of work or substantially reduces the chance of undry typos we're probably better off with explicit code.The
iter()
method is no longer generated byvector_macros
, it's now part of theVector
trait. This allows generic implementations to create vector iterators.The
TryFrom
methods forSEXP -> impl Vector
now create empty vectors if passedNULL
. This in turn is used in&RObject -> Vec<T>
(this was necessary because the existing conversion method forRObject -> Vec<i32>
now uses the new helper for&RObject
and it supportsNULL
inputs, which seems reasonable enough for a conversion method).