-
Notifications
You must be signed in to change notification settings - Fork 28
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 interval tree #63
base: master
Are you sure you want to change the base?
Conversation
Thanks for this! Is this code based on another crate or an existing implementation? Do you see these intervals being used for text properties or overlays? I am not sure what the association is with plists, because I believe that plists are just regular lists are the hood. |
just updated This is based on an textbook's rbtree implementation(/Algorithms/, 4th ed). I'm not familiar with overlays, but text properties are stored as plists, like |
src/textprops.rs
Outdated
// if no key1 found, append them | ||
if !found { | ||
let pl = plist_i.untag(); | ||
changed = true; | ||
let new_cons: Gc<ListType<'ob>> = Cons::new(key1, Cons::new(val1?, pl, cx), cx).into(); | ||
plist_i = new_cons; // TODO this does not work |
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.
How should I turn a Nil Cons to a contented one?
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.
anything that is a subset of an Object
can be converted to an Object
via into
. So if you wanted to update plist_i
you can first make it mutable
pub fn add_properties<'ob>(
...
mut plist_i: Object<'ob>,
then update it:
let new_cons: List = Cons::new(key1, Cons::new(val1?, pl, cx), cx).into();
plist_i = new_cons.into();
or even just like this
plist_i = Cons::new(key1, Cons::new(val1?, pl, cx), cx).into();
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.
thanks for this, actually it is just how I did. now i'm passing references plist_i: &mut Object<'ob>
to modify the plist inplace. i wonder whether this style is preferred.
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.
Note that Object
is just a tagged pointer, so you can't modify the underlying data via &mut
(it would be similar to having &mut &String
, where you have a mutable reference to an immutable string). if plist_i
is a Cons
, than you can use .set_car()
or .set_cdr()
.
Though looking at what you are trying to do, we want to preprend key1. But that will change the head of the list, so we can't do it mutably. Instead we should return a new plist_i
and then reassign it outside of add_properties
. Either that or append key1 (instead of preprend) and that will modify the existing list without changing the head.
Technically you are doing the same thing with &mut Object
(changing the head), but since Object
is copy, I think it is more idiomatic to return the updated value.
I added a arch doc that will hopefully help make it clearer how the types interact and how to do basic things. If you feel something is missing, please let me know. |
got another question about #[derive(Debug, Default, Trace)]
pub struct Env<'a> {
//...
pub buffer_textprops: ObjectMap<String, Slot<IntervalTree<'a>>>,
} but The IntervalTree has following structure: struct IntervalTree<'ob> {
root: Node<'ob>,
}
struct Node<'ob> {
//...
val: Object<'ob>, // text property plist
} This object should be rooted; but how should I supposed to do so? |
@dwuggh Sorry I somehow missed this comment.
What we need is to put struct Node<'ob> {
//...
val: Slot<Object<'ob>>, // text property plist
} Then we should be able to derive |
This is an interval tree implementation based on red-black tree. Merging intervals still need work, as well as updating plists.
My goal is to validate ideas in #61 , an elisp-managed concurrent (re)display models for emacs.
Emacs' implementation
emacs store every buffer or strings text property in an interval tree, defined in
intervals.h
:plist
field. Relevant functions are intextprop.c
andintervals.h
it
finds next interval of text props for redisplay incompute_stop_pos
, inxdisp.c
.set-text-properties
.position
field, is updated during redisplay, to optimize for performance.This implementation
The interval tree is based on a red-black tree, algorithms adapted from the famous book Dr. Sergewick's /Algorithms/, 4th ed.
I've looked at rust-bio's implementation as you mentioned in design.org, the arraybacked one seems not so efficient on deletion, and the AVL tree impl is similar to this one.