rune/ast/
mod.rs

1//! Abstract syntax trees for the Rune language.
2//!
3//! These are primarily made available for use in macros, where the input to the
4//! macro needs to be parsed so that it can be processed.
5//!
6//! Below we define a macro capable of taking identifiers like `hello`, and
7//! turning them into literal strings like `"hello"`.
8//!
9//! ```
10//! use rune::{Context, FromValue, Module, Vm};
11//! use rune::ast;
12//! use rune::compile;
13//! use rune::macros::{quote, MacroContext, TokenStream};
14//! use rune::parse::Parser;
15//! use rune::alloc::prelude::*;
16//! use rune::sync::Arc;
17//!
18//! #[rune::macro_]
19//! fn ident_to_string(cx: &mut MacroContext<'_, '_, '_>, stream: &TokenStream) -> compile::Result<TokenStream> {
20//!     let mut p = Parser::from_token_stream(stream, cx.input_span());
21//!     let ident = p.parse_all::<ast::Ident>()?;
22//!     let ident = cx.resolve(ident)?.try_to_owned()?;
23//!     let string = cx.lit(&ident)?;
24//!     Ok(quote!(#string).into_token_stream(cx)?)
25//! }
26//!
27//! let mut m = Module::new();
28//! m.macro_meta(ident_to_string)?;
29//!
30//! let mut context = Context::new();
31//! context.install(m)?;
32//!
33//! let runtime = Arc::try_new(context.runtime()?)?;
34//!
35//! let mut sources = rune::sources! {
36//!     entry => {
37//!         pub fn main() {
38//!             ident_to_string!(hello)
39//!         }
40//!     }
41//! };
42//!
43//! let unit = rune::prepare(&mut sources)
44//!     .with_context(&context)
45//!     .build()?;
46//!
47//! let unit = Arc::try_new(unit)?;
48//!
49//! let mut vm = Vm::new(runtime, unit);
50//! let value = vm.call(["main"], ())?;
51//! let value: String = rune::from_value(value)?;
52//!
53//! assert_eq!(value, "hello");
54//! # Ok::<_, rune::support::Error>(())
55//! ```
56
57use crate as rune;
58use crate::alloc::prelude::*;
59use crate::macros::{MacroContext, ToTokens, TokenStream};
60use crate::parse::{Parse, Parser, Peek};
61
62#[cfg(test)]
63mod testing;
64
65#[macro_use]
66/// Generated modules.
67mod generated;
68pub use self::generated::*;
69
70macro_rules! expr_parse {
71    ($ty:ident, $local:ty, $expected:literal) => {
72        impl $crate::parse::Parse for $local {
73            fn parse(p: &mut $crate::parse::Parser<'_>) -> $crate::compile::Result<Self> {
74                let t = p.tok_at(0)?;
75
76                match $crate::ast::Expr::parse(p)? {
77                    $crate::ast::Expr::$ty(expr) => Ok(expr),
78                    _ => Err($crate::compile::Error::expected(t, $expected)),
79                }
80            }
81        }
82    };
83}
84
85macro_rules! item_parse {
86    ($ty:ident, $local:ty, $expected:literal) => {
87        impl $crate::parse::Parse for $local {
88            fn parse(p: &mut $crate::parse::Parser<'_>) -> $crate::compile::Result<Self> {
89                let t = p.tok_at(0)?;
90
91                match $crate::ast::Item::parse(p)? {
92                    $crate::ast::Item::$ty(item) => Ok(item),
93                    _ => Err($crate::compile::Error::expected(t, $expected)),
94                }
95            }
96        }
97    };
98}
99
100#[cfg(test)]
101mod tests;
102
103mod attribute;
104mod block;
105mod condition;
106mod expr;
107mod expr_assign;
108mod expr_await;
109mod expr_binary;
110mod expr_block;
111mod expr_break;
112mod expr_call;
113mod expr_closure;
114mod expr_continue;
115mod expr_empty;
116mod expr_field_access;
117mod expr_for;
118mod expr_group;
119mod expr_if;
120mod expr_index;
121mod expr_let;
122mod expr_lit;
123mod expr_loop;
124mod expr_match;
125mod expr_object;
126mod expr_range;
127mod expr_return;
128mod expr_select;
129mod expr_try;
130mod expr_tuple;
131mod expr_unary;
132mod expr_vec;
133mod expr_while;
134mod expr_yield;
135mod fields;
136mod file;
137mod fn_arg;
138mod grouped;
139mod ident;
140mod item;
141mod item_const;
142mod item_enum;
143mod item_fn;
144mod item_impl;
145mod item_mod;
146mod item_struct;
147mod item_use;
148mod label;
149mod lit;
150mod lit_bool;
151mod lit_byte;
152mod lit_byte_str;
153mod lit_char;
154mod lit_number;
155mod lit_str;
156mod local;
157mod macro_call;
158mod macro_utils;
159mod pat;
160mod path;
161mod prelude;
162mod rn_type;
163mod span;
164pub(crate) mod spanned;
165mod stmt;
166mod to_ast;
167mod token;
168pub(super) mod unescape;
169mod utils;
170mod vis;
171
172pub use self::attribute::{AttrStyle, Attribute};
173pub use self::block::{Block, EmptyBlock};
174pub use self::condition::Condition;
175pub use self::expr::Expr;
176pub use self::expr_assign::ExprAssign;
177pub use self::expr_await::ExprAwait;
178pub use self::expr_binary::{BinOp, ExprBinary};
179pub use self::expr_block::ExprBlock;
180pub use self::expr_break::ExprBreak;
181pub use self::expr_call::ExprCall;
182pub use self::expr_closure::{ExprClosure, ExprClosureArgs};
183pub use self::expr_continue::ExprContinue;
184pub use self::expr_empty::ExprEmpty;
185pub use self::expr_field_access::{ExprField, ExprFieldAccess};
186pub use self::expr_for::ExprFor;
187pub use self::expr_group::ExprGroup;
188pub use self::expr_if::{ExprElse, ExprElseIf, ExprIf};
189pub use self::expr_index::ExprIndex;
190pub use self::expr_let::ExprLet;
191pub use self::expr_lit::ExprLit;
192pub use self::expr_loop::ExprLoop;
193pub use self::expr_match::{ExprMatch, ExprMatchBranch};
194pub use self::expr_object::{ExprObject, FieldAssign, ObjectIdent, ObjectKey};
195pub use self::expr_range::{ExprRange, ExprRangeLimits};
196pub use self::expr_return::ExprReturn;
197pub use self::expr_select::{ExprDefaultBranch, ExprSelect, ExprSelectBranch, ExprSelectPatBranch};
198pub use self::expr_try::ExprTry;
199pub use self::expr_tuple::ExprTuple;
200pub use self::expr_unary::{ExprUnary, UnOp};
201pub use self::expr_vec::ExprVec;
202pub use self::expr_while::ExprWhile;
203pub use self::expr_yield::ExprYield;
204pub use self::fields::Fields;
205pub use self::file::{File, Shebang};
206pub use self::fn_arg::FnArg;
207pub use self::grouped::{AngleBracketed, Braced, Bracketed, Parenthesized};
208pub use self::ident::Ident;
209pub use self::item::Item;
210pub use self::item_const::ItemConst;
211pub use self::item_enum::{ItemEnum, ItemVariant};
212pub use self::item_fn::ItemFn;
213pub use self::item_impl::ItemImpl;
214pub use self::item_mod::{ItemInlineBody, ItemMod, ItemModBody};
215pub use self::item_struct::{Field, ItemStruct};
216pub use self::item_use::{ItemUse, ItemUsePath, ItemUseSegment};
217pub use self::label::Label;
218pub use self::lit::Lit;
219pub use self::lit_bool::LitBool;
220pub use self::lit_byte::LitByte;
221pub use self::lit_byte_str::LitByteStr;
222pub use self::lit_char::LitChar;
223pub use self::lit_number::LitNumber;
224pub use self::lit_str::LitStr;
225pub use self::local::Local;
226pub use self::macro_call::MacroCall;
227pub use self::macro_utils::{EqValue, Group};
228pub use self::pat::{
229    Pat, PatBinding, PatIgnore, PatLit, PatObject, PatPath, PatRest, PatTuple, PatVec,
230};
231pub use self::path::{Path, PathKind, PathSegment, PathSegmentExpr};
232use self::prelude::*;
233pub use self::rn_type::Type;
234pub use self::span::{ByteIndex, Span};
235pub use self::spanned::{OptionSpanned, Spanned};
236pub use self::stmt::{ItemOrExpr, Stmt, StmtSemi, StmtSortKey};
237pub(crate) use self::to_ast::ToAst;
238pub use self::token::{
239    BuiltIn, CopySource, Delimiter, LitSource, Number, NumberBase, NumberSize, NumberSource,
240    NumberSuffix, NumberText, NumberValue, StrSource, StrText, Token,
241};
242pub use self::vis::Visibility;
243
244macro_rules! decl_tokens {
245    ($(($parser:ident, $name:expr, $doc:expr, $($kind:tt)*),)*) => {
246        $(
247            #[doc = $doc]
248            #[derive(Debug, TryClone, Clone, Copy, PartialEq, Eq)]
249            #[try_clone(copy)]
250            pub struct $parser {
251                /// Associated token.
252                pub span: Span,
253            }
254
255            impl Spanned for $parser {
256                fn span(&self) -> Span {
257                    self.span
258                }
259            }
260
261            impl OptionSpanned for $parser {
262                fn option_span(&self) -> Option<Span> {
263                    Some(self.span)
264                }
265            }
266
267            impl Parse for $parser {
268                fn parse(parser: &mut Parser<'_>) -> $crate::compile::Result<Self> {
269                    let t = parser.next()?;
270
271                    match t.kind {
272                        $($kind)* => Ok(Self { span: t.span }),
273                        _ => Err($crate::compile::Error::expected(t, $name)),
274                    }
275                }
276            }
277
278            impl Peek for $parser {
279                fn peek(p: &mut $crate::parse::Peeker<'_>) -> bool {
280                    matches!(p.nth(0), $($kind)*)
281                }
282            }
283
284            impl ToTokens for $parser {
285                fn to_tokens(&self, _: &mut MacroContext<'_, '_, '_>, stream: &mut TokenStream) -> alloc::Result<()> {
286                    stream.push(Token { span: self.span, kind: $($kind)* })
287                }
288            }
289        )*
290    }
291}
292
293decl_tokens! {
294    (CloseBrace, "a closing brace `}`", "closing brace", Kind::Close(Delimiter::Brace)),
295    (CloseBracket, "a closing bracket `]`", "closing bracket", Kind::Close(Delimiter::Bracket)),
296    (CloseParen, "a closing parenthesis `)`", "closing parenthesis", Kind::Close(Delimiter::Parenthesis)),
297    (CloseEmpty, "an empty closing marker", "closing marker", Kind::Close(Delimiter::Empty)),
298    (OpenBrace, "an opening brace `{`", "opening brace", Kind::Open(Delimiter::Brace)),
299    (OpenBracket, "an open bracket `[`", "opening bracket", Kind::Open(Delimiter::Bracket)),
300    (OpenParen, "an opening parenthesis `(`", "opening parenthesis", Kind::Open(Delimiter::Parenthesis)),
301    (OpenEmpty, "an empty opening marker", "opening marker", Kind::Open(Delimiter::Empty)),
302}
303
304/// The composite `is not` operation.
305#[derive(Debug, TryClone, Clone, Copy, PartialEq, Eq, Hash, ToTokens, Spanned)]
306#[try_clone(copy)]
307#[non_exhaustive]
308pub struct IsNot {
309    /// The `is` token.
310    pub is: Is,
311    /// The `not` token.
312    pub not: Not,
313}