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

Vectors and buffers #202

Closed
wants to merge 10 commits into
base: master
from

Add vector type basics, implement sorting for vecs (and lists).

  • Loading branch information...
birkenfeld committed Jun 5, 2017
commit 24248b43295f47f32fe6ba0c74cc60c9c18747f9
Copy path View file
@@ -77,7 +77,8 @@ pub fn lisp_fn(attr_ts: TokenStream, fn_ts: TokenStream) -> TokenStream {
lazy_static! {
pub static ref #sname: ::remacs_sys::Lisp_Subr = ::remacs_sys::Lisp_Subr {
header: ::remacs_sys::vectorlike_header {
size: (::remacs_sys::PVEC_SUBR << ::remacs_sys::PSEUDOVECTOR_AREA_BITS) as ::libc::ptrdiff_t,
size: (::remacs_sys::PseudovecType::PVEC_SUBR as ::libc::ptrdiff_t)
<< ::remacs_sys::PSEUDOVECTOR_AREA_BITS,
},
function: self::#fname as *const ::libc::c_void,
min_args: #min_args,
Copy path View file
@@ -17,6 +17,8 @@
extern crate libc;
use std::isize;
include!(concat!(env!("OUT_DIR"), "/definitions.rs"));
pub type Lisp_Object = EmacsInt;
@@ -33,40 +35,54 @@ pub const CHAR_MODIFIER_MASK: char_bits =
CHAR_ALT | CHAR_SUPER | CHAR_HYPER | CHAR_SHIFT | CHAR_CTL | CHAR_META;
pub const CHARACTERBITS: char_bits = 22;
pub const PSEUDOVECTOR_SIZE_BITS: libc::c_int = 12;
pub const PSEUDOVECTOR_SIZE_MASK: libc::c_int = (1 << PSEUDOVECTOR_SIZE_BITS) - 1;
pub const PSEUDOVECTOR_REST_BITS: libc::c_int = 12;
pub const PSEUDOVECTOR_REST_MASK: libc::c_int = (((1 << PSEUDOVECTOR_REST_BITS) - 1) <<
PSEUDOVECTOR_SIZE_BITS);
pub const PSEUDOVECTOR_AREA_BITS: libc::c_int = PSEUDOVECTOR_SIZE_BITS + PSEUDOVECTOR_REST_BITS;
pub const PVEC_TYPE_MASK: libc::c_int = 0x3f << PSEUDOVECTOR_AREA_BITS;
pub const PSEUDOVECTOR_FLAG: libc::ptrdiff_t = std::isize::MAX - std::isize::MAX / 2;
pub const PSEUDOVECTOR_SIZE_BITS: libc::ptrdiff_t = 12;
pub const PSEUDOVECTOR_SIZE_MASK: libc::ptrdiff_t = (1 << PSEUDOVECTOR_SIZE_BITS) - 1;
pub const PSEUDOVECTOR_REST_BITS: libc::ptrdiff_t = 12;
pub const PSEUDOVECTOR_REST_MASK: libc::ptrdiff_t = (((1 << PSEUDOVECTOR_REST_BITS) - 1) <<
PSEUDOVECTOR_SIZE_BITS);
pub const PSEUDOVECTOR_AREA_BITS: libc::ptrdiff_t = PSEUDOVECTOR_SIZE_BITS + PSEUDOVECTOR_REST_BITS;
pub const PVEC_TYPE_MASK: libc::ptrdiff_t = 0x3f << PSEUDOVECTOR_AREA_BITS;
#[repr(isize)]
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
#[allow(dead_code)]
#[allow(non_camel_case_types)]
pub enum PseudovecType {
PVEC_NORMAL_VECTOR = 0,
PVEC_FREE,
PVEC_PROCESS,
PVEC_FRAME,
PVEC_WINDOW,
PVEC_BOOL_VECTOR,
PVEC_BUFFER,
PVEC_HASH_TABLE,
PVEC_TERMINAL,
PVEC_WINDOW_CONFIGURATION,
PVEC_SUBR,
PVEC_OTHER,
PVEC_XWIDGET,
PVEC_XWIDGET_VIEW,
PVEC_THREAD,
PVEC_MUTEX,
PVEC_CONDVAR,
pub type pvec_type = libc::c_int;
pub const PVEC_NORMAL_VECTOR: pvec_type = 0;
pub const PVEC_FREE: pvec_type = 1;
pub const PVEC_PROCESS: pvec_type = 2;
pub const PVEC_FRAME: pvec_type = 3;
pub const PVEC_WINDOW: pvec_type = 4;
pub const PVEC_BOOL_VECTOR: pvec_type = 5;
pub const PVEC_BUFFER: pvec_type = 6;
pub const PVEC_HASH_TABLE: pvec_type = 7;
pub const PVEC_TERMINAL: pvec_type = 8;
pub const PVEC_WINDOW_CONFIGURATION: pvec_type = 9;
pub const PVEC_SUBR: pvec_type = 10;
pub const PVEC_OTHER: pvec_type = 11;
pub const PVEC_XWIDGET: pvec_type = 12;
pub const PVEC_XWIDGET_VIEW: pvec_type = 13;
pub const PVEC_COMPILED: pvec_type = 14;
pub const PVEC_CHAR_TABLE: pvec_type = 15;
pub const PVEC_SUB_CHAR_TABLE: pvec_type = 16;
pub const PVEC_FONT: pvec_type = 17;
/* These should be last, check internal_equal to see why. */
PVEC_COMPILED,
PVEC_CHAR_TABLE,
PVEC_SUB_CHAR_TABLE,
PVEC_FONT, /* Should be last because it's used for range checking. */
}
#[derive(Debug)]
#[repr(C)]
pub struct vectorlike_header {
pub size: libc::ptrdiff_t,
}
// XXX: this can also be char on some archs
pub type bits_word = libc::size_t;
/// Representation of an Emacs Lisp function symbol.
#[derive(Debug)]
#[repr(C)]
@@ -662,6 +678,8 @@ extern "C" {
pub static Qlistp: Lisp_Object;
pub static Qmarkerp: Lisp_Object;
pub static Qwholenump: Lisp_Object;
pub static Qvectorp: Lisp_Object;
pub static Qsequencep: Lisp_Object;
pub fn Fcons(car: Lisp_Object, cdr: Lisp_Object) -> Lisp_Object;
@@ -679,6 +697,7 @@ extern "C" {
props: bool,
ht: Lisp_Object)
-> bool;
pub fn call2(fn_: Lisp_Object, arg1: Lisp_Object, arg2: Lisp_Object) -> Lisp_Object;
// These signal an error, therefore are marked as non-returning.
pub fn circular_list(tail: Lisp_Object) -> !;
Copy path View file
@@ -28,6 +28,7 @@ mod numbers;
mod objects;
mod strings;
mod symbols;
mod vectors;
mod character;
mod base64;
mod crypto;
@@ -77,6 +78,9 @@ pub use symbols::Fsymbolp;
pub use strings::Fstring_equal;
pub use strings::Fstring_as_multibyte;
pub use strings::Fstring_to_multibyte;
pub use vectors::Flength;
pub use vectors::Fsort;
pub use lists::merge;
// Cryptographic functions used in the C codebase.
pub use crypto::sha256_buffer;
@@ -160,6 +164,7 @@ pub extern "C" fn rust_init_syms() {
defsubr(&*lists::Slax_plist_put);
defsubr(&*lists::Slist);
defsubr(&*lists::Smake_list);
defsubr(&*lists::Ssafe_length);
defsubr(&*marker::Smarkerp);
defsubr(&*strings::Sstringp);
defsubr(&*strings::Sbase64_encode_string);
@@ -170,6 +175,8 @@ pub extern "C" fn rust_init_syms() {
defsubr(&*strings::Sstring_to_multibyte);
defsubr(&*character::Smax_char);
defsubr(&*character::Scharacterp);
defsubr(&*vectors::Slength);
defsubr(&*vectors::Ssort);
floatfns::init_float_syms();
}
Copy path View file
@@ -9,16 +9,19 @@ extern crate libc;
#[cfg(test)]
use std::cmp::max;
use std::mem;
use std::slice;
use std::ops::Deref;
use std::fmt::{Debug, Formatter, Error};
use marker::{LispMarker, marker_position};
use multibyte::{LispStringRef, MAX_CHAR};
use vectors::LispVectorlikeRef;
use remacs_sys::{EmacsInt, EmacsUint, EmacsDouble, EMACS_INT_MAX, EMACS_INT_SIZE,
EMACS_FLOAT_SIZE, USE_LSB_TAG, GCTYPEBITS, wrong_type_argument, Qstringp,
Qnumber_or_marker_p, Qt, make_float, Qlistp, Qintegerp, Qconsp, circular_list,
internal_equal, Fcons, CHECK_IMPURE, Qnumberp, Qfloatp, Qwholenump};
internal_equal, Fcons, CHECK_IMPURE, Qnumberp, Qfloatp, Qwholenump, Qvectorp,
SYMBOL_NAME};
use remacs_sys::Lisp_Object as CLisp_Object;
// TODO: tweak Makefile to rebuild C files if this changes.
@@ -180,9 +183,17 @@ pub enum LispMiscType {
// If needed, we can calculate all variants size and allocate properly.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
#[derive(Debug)]
pub struct ExternalPtr<T>(*mut T);
impl<T> Clone for ExternalPtr<T> {
fn clone(&self) -> Self {
ExternalPtr::new(self.0)
}
}
impl<T> Copy for ExternalPtr<T> {}
impl<T> ExternalPtr<T> {
pub fn new(p: *mut T) -> ExternalPtr<T> {
ExternalPtr(p)
@@ -286,6 +297,15 @@ impl LispObject {
LispObject::from_fixnum_truncated(n)
}
#[inline]
pub fn int_or_float_from_fixnum(n: EmacsInt) -> LispObject {
if n < MOST_NEGATIVE_FIXNUM || n > MOST_POSITIVE_FIXNUM {
Self::from_float(n as f64)
} else {
Self::from_fixnum(n)
}
}
#[inline]
unsafe fn to_fixnum_unchecked(self) -> EmacsInt {
let raw = self.to_raw();
@@ -342,6 +362,37 @@ impl LispObject {
}
}
// Vectorlike support (LispType == 5)
impl LispObject {
pub fn is_vectorlike(self) -> bool {
self.get_type() == LispType::Lisp_Vectorlike
}
pub fn is_vector(self) -> bool {
self.as_vectorlike().map_or(false, |v| v.is_vector())
}
#[inline]
#[allow(dead_code)]
pub fn as_vectorlike(self) -> Option<LispVectorlikeRef> {
if self.is_vectorlike() {
Some(LispVectorlikeRef::new(unsafe { mem::transmute(self.get_untaggedptr()) }))
} else {
None
}
}
#[inline]
pub fn as_vectorlike_or_error(self) -> LispVectorlikeRef {
if self.is_vectorlike() {
LispVectorlikeRef::new(unsafe { mem::transmute(self.get_untaggedptr()) })
} else {
unsafe { wrong_type_argument(Qvectorp, self.to_raw()) }
}
}
}
// Cons support (LispType == 6 | 3)
/// From FOR_EACH_TAIL_INTERNAL in lisp.h
@@ -703,6 +754,13 @@ impl LispObject {
/// of arguments.
pub const MANY: i16 = -2;
/// Internal function to get a displayable string out of a Lisp string.
fn display_string(obj: LispObject) -> String {
let mut s = obj.as_string().unwrap();
let slice = unsafe { slice::from_raw_parts(s.data_ptr(), s.len_bytes() as usize) };
String::from_utf8_lossy(slice).into_owned()
}
impl Debug for LispObject {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
let ty = self.get_type();
@@ -714,31 +772,54 @@ impl Debug for LispObject {
self.to_raw())?;
return Ok(());
}
if self == &Qnil {
return write!(f, "nil");
}
match ty {
LispType::Lisp_Symbol => {
write!(f, "#<SYMBOL @ {:#X}: VAL({:#X})>", self_ptr, self.to_raw())?;
let name = LispObject::from_raw(unsafe { SYMBOL_NAME(self.to_raw()) });
write!(f, "'{}", display_string(name))?;
}
LispType::Lisp_Cons => {
write!(f, "#<CONS @ {:#X}: VAL({:#X})>", self_ptr, self.to_raw())?;
let mut cdr = *self;
write!(f, "'(")?;
while let Some(cons) = cdr.as_cons() {
write!(f, "{:?} ", cons.car())?;
cdr = cons.cdr();
}
if cdr == Qnil {
write!(f, ")")?;
} else {
write!(f, ". {:?}", cdr)?;
}
}
LispType::Lisp_Float => {
write!(f, "#<FLOAT @ {:#X}: VAL({:#X})>", self_ptr, self.to_raw())?;
write!(f, "{}", self.as_float().unwrap())?;
}
LispType::Lisp_Vectorlike => {
write!(f,
"#<VECTOR-LIKE @ {:#X}: VAL({:#X})>",
self_ptr,
self.to_raw())?;
let vl = self.as_vectorlike().unwrap();
if vl.is_vector() {
write!(f, "[")?;
for el in vl.as_vector().unwrap().as_slice() {
write!(f, "{:?} ", el)?;
}
write!(f, "]")?;
} else {
write!(f,
"#<VECTOR-LIKE @ {:#X}: VAL({:#X})>",
self_ptr,
self.to_raw())?;
}
}
LispType::Lisp_Int0 |
LispType::Lisp_Int1 => {
write!(f, "#<INT @ {:#X}: VAL({:#X})>", self_ptr, self.to_raw())?;
write!(f, "{}", self.as_fixnum().unwrap())?;
}
LispType::Lisp_Misc => {
write!(f, "#<MISC @ {:#X}: VAL({:#X})>", self_ptr, self.to_raw())?;
}
LispType::Lisp_String => {
write!(f, "#<STRING @ {:#X}: VAL({:#X})>", self_ptr, self.to_raw())?;
write!(f, "{:?}", display_string(*self))?;
}
}
Ok(())
Oops, something went wrong.
ProTip! Use n and p to navigate between commits in a pull request.