Skip to main content

rune/modules/macros/
builtin.rs

1//! Built-in macros.
2
3use crate as rune;
4use crate::compile::{self, ErrorKind};
5use crate::macros::{quote, MacroContext, TokenStream};
6use crate::{ContextError, Module};
7
8/// Built-in macros.
9#[rune::module(::std::macros::builtin)]
10pub fn module() -> Result<Module, ContextError> {
11    let mut m = Module::from_meta(self::module__meta)?.with_unique("std::macros::builtin");
12    m.macro_meta(file)?;
13    m.macro_meta(line)?;
14    Ok(m)
15}
16
17/// Return the line in the current file.
18///
19/// # Examples
20///
21/// ```rune
22/// println!("{}:{}: Something happened", file!(), line!());
23/// ```
24#[rune::macro_]
25pub(crate) fn line(
26    cx: &mut MacroContext<'_, '_, '_>,
27    stream: &TokenStream,
28) -> compile::Result<TokenStream> {
29    use crate as rune;
30
31    expect_no_input(stream)?;
32
33    let stream = quote!(
34        #[builtin]
35        line!()
36    );
37
38    Ok(stream.into_token_stream(cx)?)
39}
40
41/// Return the name of the current file.
42///
43/// # Examples
44///
45/// ```rune
46/// println!("{}:{}: Something happened", file!(), line!());
47/// ```
48#[rune::macro_]
49pub(crate) fn file(
50    cx: &mut MacroContext<'_, '_, '_>,
51    stream: &TokenStream,
52) -> compile::Result<TokenStream> {
53    use crate as rune;
54
55    expect_no_input(stream)?;
56
57    let stream = quote!(
58        #[builtin]
59        file!()
60    );
61
62    Ok(stream.into_token_stream(cx)?)
63}
64
65/// Refuse the input of a macro which takes none.
66///
67/// The tokens are looked at rather than parsed, since a macro which has nothing
68/// to parse has no business building a syntax tree to find that out.
69fn expect_no_input(stream: &TokenStream) -> compile::Result<()> {
70    let Some(token) = stream.into_iter().next() else {
71        return Ok(());
72    };
73
74    Err(compile::Error::new(
75        token.span,
76        ErrorKind::ExpectedEof { actual: token.kind },
77    ))
78}