Skip to main content

emacs/
symbol.rs

1use crate::{Env, Result, Value, global::{GlobalRef, OnceGlobalRef}};
2
3/// Defines static [`&OnceGlobalRef`] variables that point to corresponding Lisp symbols.
4///
5/// This macro accepts a space-separated list of identifiers, and determine the Lisp symbol names by
6/// replacing underscores with hyphens, or by explicit mappings in the form of `=> "symbol-name"`.
7///
8/// It can be used only once per Rust `mod`.
9///
10/// If a symbol is bound to a function, the variable can be used to call the function via
11/// [Env::call]. Unlike with [`use_functions!`], this goes through the indirection of symbol lookup.
12///
13/// [`&OnceGlobalRef`]: OnceGlobalRef
14/// [`use_functions!`]: crate::use_functions
15#[macro_export]
16macro_rules! use_symbols {
17    ($( $name:ident $( => $lisp_name:expr )? )*) => {
18        $crate::global_refs! {__emrs_init_global_refs_to_symbols__(init_to_symbol) =>
19            $( $name $( => $lisp_name )? )*
20        }
21    }
22}
23
24use_symbols! {
25    nil t
26    error
27    rust_error
28    rust_panic
29    rust_wrong_type_user_ptr
30}
31
32pub trait IntoLispSymbol<'e> {
33    fn into_lisp_symbol(self, env: &'e Env) -> Result<Value<'e>>;
34}
35
36impl<'e> IntoLispSymbol<'e> for Value<'e> {
37    #[inline(always)]
38    fn into_lisp_symbol(self, _: &'e Env) -> Result<Value<'e>> {
39        Ok(self)
40    }
41}
42
43impl<'e, T: AsRef<str>> IntoLispSymbol<'e> for T {
44    #[inline(always)]
45    fn into_lisp_symbol(self, env: &'e Env) -> Result<Value<'e>> {
46        env.intern(self.as_ref())
47    }
48}
49
50impl<'e> IntoLispSymbol<'e> for &'e GlobalRef {
51    #[inline(always)]
52    fn into_lisp_symbol(self, env: &'e Env) -> Result<Value<'e>> {
53        self.bind(env).into_lisp_symbol(env)
54    }
55}
56
57impl<'e> IntoLispSymbol<'e> for &'e OnceGlobalRef {
58    #[inline(always)]
59    fn into_lisp_symbol(self, env: &'e Env) -> Result<Value<'e>> {
60        self.bind(env).into_lisp_symbol(env)
61    }
62}