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

Bringing over some hash-table related functions to remacs. #251

Merged
merged 17 commits into from Jul 29, 2017
Commits
Jump to file or symbol
Failed to load files and symbols.
+226 −46
Diff settings

Always

Just for now

Copy path View file
@@ -18,9 +18,9 @@ extern crate libc;
pub mod libm;
use std::isize;
use libc::{c_char, c_uchar, c_short, c_int, c_double, c_void, ptrdiff_t, size_t, off_t, time_t,
timespec};
use libc::{c_char, c_uchar, c_short, c_int, c_double, c_float, c_void, ptrdiff_t, size_t, off_t,
time_t, timespec};
include!(concat!(env!("OUT_DIR"), "/definitions.rs"));
@@ -94,7 +94,7 @@ pub enum Lisp_Type {
Lisp_Float = 7,
}
#[repr(isize)]

This comment has been minimized.

@DavidDeSimone

DavidDeSimone Jul 18, 2017

Collaborator

I still need to look into why we were repr(isize) here, and if we need to switch over to repr(C) now that we are invoking a C function with this enum.

This comment has been minimized.

@DavidDeSimone

DavidDeSimone Jul 22, 2017

Collaborator

Based on discussions in other threads, I believe that changing this to repr(C) is the right call.

#[repr(C)]
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum PseudovecType {
PVEC_NORMAL_VECTOR = 0,
@@ -135,7 +135,6 @@ pub enum TextCursorKinds {
HBAR_CURSOR,
}
// XXX: this can also be char on some archs
pub type bits_word = size_t;
/// Representation of an Emacs Lisp function symbol.
@@ -1205,6 +1204,32 @@ pub struct emacs_globals {
pub f_x_use_underline_position_properties: bool,
}
#[repr(C)]
pub struct hash_table_test {
pub name: Lisp_Object,
pub user_hash_function: Lisp_Object,
pub user_cmp_function: Lisp_Object,
pub cmpfn: extern "C" fn(t: *mut hash_table_test, a: Lisp_Object, b: Lisp_Object) -> bool,
pub hashfn: extern "C" fn(t: *mut hash_table_test, a: Lisp_Object) -> EmacsUint,
}
#[repr(C)]
pub struct Lisp_Hash_Table {
pub header: Lisp_Vectorlike_Header,
pub weak: Lisp_Object,
pub hash: Lisp_Object,
pub next: Lisp_Object,
pub index: Lisp_Object,
pub count: ptrdiff_t,
pub next_free: ptrdiff_t,
pub pure_: bool, // pure is a reserved keyword in Rust
pub rehash_threshold: c_float,
pub rehash_size: c_float,
pub key_and_value: Lisp_Object,
pub test: hash_table_test,
pub next_weak: *mut Lisp_Hash_Table,
}
extern "C" {
pub static mut globals: emacs_globals;
pub static current_thread: *mut thread_state;
@@ -1256,6 +1281,7 @@ extern "C" {
pub static Qfont_spec: Lisp_Object;
pub static Qfont_entity: Lisp_Object;
pub static Qfont_object: Lisp_Object;
pub static Qhash_table_p: Lisp_Object;
pub static Qwrite_region: Lisp_Object;
pub static Qbuffer_file_coding_system: Lisp_Object;
pub static Qfont_extra_type: Lisp_Object;
@@ -1277,6 +1303,7 @@ extern "C" {
pub fn Fcons(car: Lisp_Object, cdr: Lisp_Object) -> Lisp_Object;
pub fn Fcurrent_buffer() -> Lisp_Object;
pub fn Fsignal(error_symbol: Lisp_Object, data: Lisp_Object) -> !;
pub fn Fcopy_sequence(seq: Lisp_Object) -> Lisp_Object;
pub fn Fbuffer_file_name(buffer: Lisp_Object) -> Lisp_Object;
pub fn Ffind_operation_coding_system(nargs: ptrdiff_t, args: *mut Lisp_Object) -> Lisp_Object;
pub fn Flocal_variable_p(variable: Lisp_Object, buffer: Lisp_Object) -> Lisp_Object;
@@ -1358,6 +1385,13 @@ extern "C" {
multibyte: bool,
nchars_return: *mut ptrdiff_t,
) -> ptrdiff_t;
pub fn allocate_pseudovector(
vecsize: c_int,
offset1: c_int,
offset2: c_int,
pvec_type: PseudovecType,
) -> *mut Lisp_Vector;
}
/// Contains C definitions from the font.h header.
Copy path View file
@@ -0,0 +1,90 @@
use remacs_macros::lisp_fn;
use lisp::{LispObject, ExternalPtr};
use remacs_sys::{Lisp_Hash_Table, PseudovecType, Fcopy_sequence};
use std::ptr;
pub type LispHashTableRef = ExternalPtr<Lisp_Hash_Table>;
impl LispHashTableRef {
pub fn allocate() -> LispHashTableRef {
let vec_ptr =
allocate_pseudovector!(Lisp_Hash_Table, count, PseudovecType::PVEC_HASH_TABLE);
LispHashTableRef::new(vec_ptr)
}
pub unsafe fn copy(&mut self, other: LispHashTableRef) {
ptr::copy_nonoverlapping(other.as_ptr(), self.as_mut(), 1);
}
pub fn set_next_weak(&mut self, other: LispHashTableRef) {
self.next_weak = other.as_ptr() as *mut Lisp_Hash_Table;
}
pub fn get_next_weak(&self) -> LispHashTableRef {
LispHashTableRef::new(self.next_weak)
}
pub fn set_hash(&mut self, hash: LispObject) {
self.hash = hash.to_raw();
}
pub fn get_hash(&self) -> LispObject {
LispObject::from_raw(self.hash)
}
pub fn set_next(&mut self, next: LispObject) {
self.next = next.to_raw();
}
pub fn get_next(&self) -> LispObject {
LispObject::from_raw(self.next)
}
pub fn set_index(&mut self, index: LispObject) {
self.index = index.to_raw();
}
pub fn get_index(&self) -> LispObject {
LispObject::from_raw(self.index)
}
pub fn get_key_and_value(&self) -> LispObject {
LispObject::from_raw(self.key_and_value)
}
pub fn set_key_and_value(&mut self, key_and_value: LispObject) {
self.key_and_value = key_and_value.to_raw();
}
pub fn get_weak(&self) -> LispObject {
LispObject::from_raw(self.weak)
}
}
/// Return a copy of hash table TABLE.
/// Keys and values are not copied, only the table itself is.
#[lisp_fn]
fn copy_hash_table(htable: LispObject) -> LispObject {
let mut table = htable.as_hash_table_or_error();
let mut new_table = LispHashTableRef::allocate();
unsafe { new_table.copy(table) };
assert!(new_table.as_ptr() != table.as_ptr());
let key_and_value = LispObject::from_raw(unsafe {
Fcopy_sequence(new_table.get_key_and_value().to_raw())
});
let hash = LispObject::from_raw(unsafe { Fcopy_sequence(new_table.get_hash().to_raw()) });
let next = LispObject::from_raw(unsafe { Fcopy_sequence(new_table.get_next().to_raw()) });
let index = LispObject::from_raw(unsafe { Fcopy_sequence(new_table.get_index().to_raw()) });
new_table.set_key_and_value(key_and_value);
new_table.set_hash(hash);
new_table.set_next(next);
new_table.set_index(index);
if new_table.get_weak().is_not_nil() {
new_table.set_next_weak(table.get_next_weak());
table.set_next_weak(new_table);
}
LispObject::from_hash_table(new_table)
}
Copy path View file
@@ -33,6 +33,7 @@ mod numbers;
mod objects;
mod strings;
mod symbols;
#[macro_use]
mod vectors;
mod character;
mod base64;
@@ -41,6 +42,7 @@ mod str2sig;
mod multibyte;
mod buffers;
mod windows;
mod hashtable;
mod interactive;
mod process;
mod fonts;
@@ -244,6 +246,7 @@ pub extern "C" fn rust_init_syms() {
defsubr(&*vectors::Svector_or_char_table_p);
defsubr(&*vectors::Svectorp);
defsubr(&*vectors::Slength);
defsubr(&*hashtable::Scopy_hash_table);
defsubr(&*fonts::Sfontp);
defsubr(&*crypto::Smd5);
defsubr(&*crypto::Ssecure_hash);
Copy path View file
@@ -9,22 +9,24 @@ use std::mem;
use std::slice;
use std::ops::{Deref, DerefMut};
use std::fmt::{Debug, Formatter, Error};
use libc::{c_void, intptr_t};
use libc::{c_void, intptr_t, uintptr_t};
use multibyte::{Codepoint, LispStringRef, MAX_CHAR};
use symbols::LispSymbolRef;
use vectors::LispVectorlikeRef;
use buffers::LispBufferRef;
use windows::LispWindowRef;
use marker::LispMarkerRef;
use hashtable::LispHashTableRef;
use fonts::LispFontRef;
use remacs_sys::{EmacsInt, EmacsUint, EmacsDouble, VALMASK, VALBITS, INTTYPEBITS, INTMASK,
USE_LSB_TAG, MOST_POSITIVE_FIXNUM, MOST_NEGATIVE_FIXNUM, Lisp_Type,
Lisp_Misc_Any, Lisp_Misc_Type, Lisp_Float, Lisp_Cons, Lisp_Object, lispsym,
make_float, circular_list, internal_equal, Fcons, CHECK_IMPURE, Qnil, Qt,
Qnumberp, Qfloatp, Qstringp, Qsymbolp, Qnumber_or_marker_p, Qwholenump, Qvectorp,
Qcharacterp, Qlistp, Qintegerp, Qconsp, SYMBOL_NAME, PseudovecType, EqualKind};
Qcharacterp, Qlistp, Qintegerp, Qhash_table_p, Qconsp, SYMBOL_NAME,
PseudovecType, EqualKind};
// TODO: tweak Makefile to rebuild C files if this changes.
@@ -96,6 +98,22 @@ impl LispObject {
unsafe { mem::transmute(res) }
}
pub fn tag_ptr<T>(external: ExternalPtr<T>, ty: Lisp_Type) -> LispObject {

This comment has been minimized.

@Wilfred

Wilfred Jul 23, 2017

Owner

Handy!

let raw = external.as_ptr() as intptr_t;
let res;
if USE_LSB_TAG {
let ptr = raw as intptr_t;
let tag = ty as intptr_t;
res = (ptr + tag) as EmacsInt;
} else {
let ptr = raw as EmacsUint as uintptr_t;
let tag = ty as EmacsUint as uintptr_t;
res = ((tag << VALBITS) + ptr) as EmacsInt;
}
LispObject::from_raw(res)
}
#[inline]
pub fn get_untaggedptr(self) -> *mut c_void {
(self.to_raw() & VALMASK) as intptr_t as *mut c_void
@@ -182,6 +200,10 @@ impl<T> ExternalPtr<T> {
pub fn as_ptr(&self) -> *const T {
self.0
}
pub fn as_mut(&mut self) -> *mut T {
self.0
}
}
impl<T> Deref for ExternalPtr<T> {
@@ -485,6 +507,36 @@ impl LispObject {
}
}
impl LispObject {
pub fn as_hash_table_or_error(&self) -> LispHashTableRef {
if self.is_hash_table() {
LispHashTableRef::new(unsafe { mem::transmute(self.get_untaggedptr()) })
} else {
wrong_type!(Qhash_table_p, *self);
}
}
pub fn as_hash_table(&self) -> Option<LispHashTableRef> {
if self.is_hash_table() {
Some(LispHashTableRef::new(
unsafe { mem::transmute(self.get_untaggedptr()) },
))
} else {
None
}
}
pub fn from_hash_table(hashtable: LispHashTableRef) -> LispObject {
let object = LispObject::tag_ptr(hashtable, Lisp_Type::Lisp_Vectorlike);
debug_assert!(
object.is_vectorlike() && object.get_untaggedptr() == hashtable.as_ptr() as *mut c_void
);
debug_assert!(object.is_hash_table());
object
}
}
// Cons support (LispType == 6 | 3)
/// From FOR_EACH_TAIL_INTERNAL in lisp.h
Copy path View file
@@ -256,3 +256,43 @@ pub fn mutexp(object: LispObject) -> LispObject {
pub fn condition_variable_p(object: LispObject) -> LispObject {
LispObject::from_bool(object.is_condition_variable())
}
macro_rules! offset_of {
($ty:ty, $field:ident) => {
&(*(0 as *const $ty)).$field as *const _ as usize
}
}
lazy_static! {
pub static ref HEADER_SIZE: usize = {
unsafe { offset_of!(::remacs_sys::Lisp_Vector, contents) }
};
pub static ref WORD_SIZE: usize = {
::std::mem::size_of::<::remacs_sys::Lisp_Object>()
};
}
/// Equivalent to PSEUDOVECSIZE in C
macro_rules! pseudovecsize {
($ty: ty, $field: ident) => {
((offset_of!($ty, $field) - *::vectors::HEADER_SIZE) / *::vectors::WORD_SIZE)
}
}
/// Equivalent to VECSIZE in C
macro_rules! vecsize {
($ty: ty) => {
((::std::mem::size_of::<$ty>()
- *::vectors::HEADER_SIZE + *::vectors::WORD_SIZE - 1) / *::vectors::WORD_SIZE)
}
}
/// Equivalent to ALLOCATE_PSEUDOVECTOR in C
macro_rules! allocate_pseudovector {
($ty: ty, $field: ident, $vectype: expr) => {
unsafe { ::remacs_sys::allocate_pseudovector(vecsize!($ty) as ::libc::c_int,
pseudovecsize!($ty, $field) as ::libc::c_int,
pseudovecsize!($ty, $field) as ::libc::c_int,
$vectype) as *mut $ty}
}
}
Oops, something went wrong.
ProTip! Use n and p to navigate between commits in a pull request.