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

Port indirect-variable functions #357

Merged
merged 3 commits into from Oct 14, 2017
Jump to file or symbol
Failed to load files and symbols.
+77 −53
Diff settings

Always

Just for now

Copy path View file
@@ -208,6 +208,14 @@ pub enum Symbol_Interned {
InternedInInitialObarray = 2,
}
#[repr(C)]
pub enum Symbol_Redirect {
PlainVal = 4,
VarAlias = 1,
Localized = 2,
Forwarded = 3,
}
/// This struct has 4 bytes of padding, representing the bitfield that
/// lives at the top of a Lisp_Symbol. The first 10 bits of this field are
/// used.
@@ -996,6 +1004,7 @@ extern "C" {
pub static Qfont_extra_type: Lisp_Object;
pub static Qsetting_constant: Lisp_Object;
pub static Qcyclic_function_indirection: Lisp_Object;
pub static Qcyclic_variable_indirection: Lisp_Object;
pub static Qmd5: Lisp_Object;
pub static Qsha1: Lisp_Object;
@@ -1029,6 +1038,7 @@ extern "C" {
pub fn make_float(float_value: c_double) -> Lisp_Object;
pub fn make_string(s: *const c_char, length: ptrdiff_t) -> Lisp_Object;
pub fn make_lisp_ptr(ptr: *const c_void, ty: Lisp_Type) -> Lisp_Object;
pub fn make_lisp_symbol(ptr: *mut Lisp_Symbol) -> Lisp_Object;
pub fn build_string(s: *const c_char) -> Lisp_Object;
pub fn make_unibyte_string(s: *const c_char, length: ptrdiff_t) -> Lisp_Object;
pub fn make_uninit_string(length: EmacsInt) -> Lisp_Object;
Copy path View file
@@ -146,6 +146,8 @@ pub use symbols::Ffboundp;
pub use symbols::Fsymbol_function;
pub use symbols::Fsymbol_plist;
pub use symbols::Fkeywordp;
pub use symbols::Findirect_variable;
pub use symbols::indirect_variable;
pub use strings::Fstring_equal;
pub use strings::Fstring_as_multibyte;
pub use strings::Fstring_to_multibyte;
@@ -292,6 +294,7 @@ pub extern "C" fn rust_init_syms() {
defsubr(&*symbols::Ssetplist);
defsubr(&*symbols::Sfmakunbound);
defsubr(&*symbols::Skeywordp);
defsubr(&*symbols::Sindirect_variable);
defsubr(&*lists::Sconsp);
defsubr(&*lists::Ssetcar);
defsubr(&*lists::Ssetcdr);
Copy path View file
@@ -1,10 +1,13 @@
use remacs_macros::lisp_fn;
use std::mem;
use lisp::{LispObject, ExternalPtr};
use remacs_sys::{Lisp_Symbol, Symbol_Interned, Qsetting_constant};
use remacs_sys::{make_lisp_symbol, Lisp_Symbol, Symbol_Interned, Symbol_Redirect,
Qsetting_constant, Qcyclic_variable_indirection};
pub type LispSymbolRef = ExternalPtr<Lisp_Symbol>;
const FLAG_INTERNED: u32 = 0b11 << 6; // 7 and 8 bits
const FLAG_REDIRECT: u32 = 0b1110; // bits 2, 3 and 4
impl LispSymbolRef {
pub fn symbol_name(&self) -> LispObject {
@@ -31,6 +34,49 @@ impl LispSymbolRef {
self.symbol_bitfield & FLAG_INTERNED ==
(Symbol_Interned::InternedInInitialObarray as u32) << 6
}
pub fn is_alias(&self) -> bool {
self.symbol_bitfield & FLAG_REDIRECT == (Symbol_Redirect::VarAlias as u32) << 1
}
pub fn get_alias(&self) -> LispSymbolRef {
LispSymbolRef::new(unsafe { mem::transmute(self.val.alias) })
}
pub fn as_lisp_obj(mut self) -> LispObject {
LispObject::from_raw(unsafe { make_lisp_symbol(self.as_mut()) })
}
/// Return the symbol holding SYMBOL's value. Signal
/// `cyclic-variable-indirection' if SYMBOL's chain of variable
/// indirections contains a loop.
pub fn get_indirect_variable(self) -> Self {
let mut tortoise = self;
let mut hare = self;
while hare.is_alias() {
hare = hare.get_alias();
if !hare.is_alias() {
break;
}
hare = hare.get_alias();
tortoise = tortoise.get_alias();
if hare == tortoise {
xsignal!(Qcyclic_variable_indirection, hare.as_lisp_obj())
}
}
hare
}
}
// Wrapper around LispSymbolRef::get_indirect_variable()
// could be removed when all C references are ported
#[no_mangle]
pub unsafe extern "C" fn indirect_variable(symbol: *mut Lisp_Symbol) -> *mut Lisp_Symbol {
LispSymbolRef::new(symbol).get_indirect_variable().as_mut()
}
/// Return t if OBJECT is a symbol.
@@ -107,3 +153,20 @@ fn keywordp(object: LispObject) -> LispObject {
LispObject::constant_nil()
}
}
/// Return the variable at the end of OBJECT's variable chain.
/// If OBJECT is a symbol, follow its variable indirections (if any), and
/// return the variable at the end of the chain of aliases. See Info node
/// `(elisp)Variable Aliases'.
///
/// If OBJECT is not a symbol, just return it. If there is a loop in the
/// chain of aliases, signal a `cyclic-variable-indirection' error.
#[lisp_fn(name = "indirect-variable", c_name = "indirect_variable")]
fn indirect_variable_lisp(object: LispObject) -> LispObject {
if let Some(symbol) = object.as_symbol() {
let val = symbol.get_indirect_variable();
val.as_lisp_obj()
} else {
object
}
}
Copy path View file
@@ -506,57 +506,6 @@ Value, if non-nil, is a list (interactive SPEC). */)
Getting and Setting Values of Symbols
***********************************************************************/
/* Return the symbol holding SYMBOL's value. Signal
`cyclic-variable-indirection' if SYMBOL's chain of variable
indirections contains a loop. */
struct Lisp_Symbol *
indirect_variable (struct Lisp_Symbol *symbol)
{
struct Lisp_Symbol *tortoise, *hare;
hare = tortoise = symbol;
while (hare->redirect == SYMBOL_VARALIAS)
{
hare = SYMBOL_ALIAS (hare);
if (hare->redirect != SYMBOL_VARALIAS)
break;
hare = SYMBOL_ALIAS (hare);
tortoise = SYMBOL_ALIAS (tortoise);
if (hare == tortoise)
{
Lisp_Object tem;
XSETSYMBOL (tem, symbol);
xsignal1 (Qcyclic_variable_indirection, tem);
}
}
return hare;
}
DEFUN ("indirect-variable", Findirect_variable, Sindirect_variable, 1, 1, 0,
doc: /* Return the variable at the end of OBJECT's variable chain.
If OBJECT is a symbol, follow its variable indirections (if any), and
return the variable at the end of the chain of aliases. See Info node
`(elisp)Variable Aliases'.
If OBJECT is not a symbol, just return it. If there is a loop in the
chain of aliases, signal a `cyclic-variable-indirection' error. */)
(Lisp_Object object)
{
if (SYMBOLP (object))
{
struct Lisp_Symbol *sym = indirect_variable (XSYMBOL (object));
XSETSYMBOL (object, sym);
}
return object;
}
/* Given the raw contents of a symbol value cell,
return the Lisp value of the symbol.
This does not handle buffer-local variables; use
@@ -2704,7 +2653,6 @@ syms_of_data (void)
DEFSYM (Qinteractive_form, "interactive-form");
DEFSYM (Qdefalias_fset_function, "defalias-fset-function");
defsubr (&Sindirect_variable);
defsubr (&Sinteractive_form);
defsubr (&Stype_of);
defsubr (&Smodule_function_p);
ProTip! Use n and p to navigate between commits in a pull request.