wright/parser/ty/
reference.rs

1//! Referenced types. Types that are defined by users or in the standard library.
2
3use crate::{
4    ast::ty::{ReferenceTy, Type},
5    lexer::token::TokenTy,
6    parser::{
7        Parser,
8        error::{ParserError, ParserErrorKind},
9        whitespace,
10    },
11    source_tracking::fragment::Fragment,
12};
13
14impl ReferenceTy {
15    /// Attempt to parse a reference type signature, i.e. `@u64`.
16    ///
17    /// This will leave the parser unmodified and return an error if it doesn't match the `@` symbol, however
18    /// if it does match the `@` symbol it will advance the parser and then may still return an error if the
19    /// `@` symbol is not followed by a type signature.
20    pub fn parse(parser: &mut Parser) -> Result<Self, ParserError> {
21        let Some(at_symbol) = parser.next_if_is(TokenTy::At) else {
22            return Err(ParserErrorKind::ExpectedReferenceTypeSignature
23                .at(parser.peek_fragment_or_rest_cloned()));
24        };
25
26        whitespace::optional_whitespace(parser);
27
28        let referenced_type = Type::parse(parser)?;
29
30        Ok(ReferenceTy {
31            matching_source: Fragment::cover(
32                &at_symbol.fragment,
33                referenced_type.matching_source(),
34            ),
35            target_ty: Box::new(referenced_type),
36        })
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use crate::{
43        ast::ty::{AtomicTyVariant, ReferenceTy},
44        lexer::Lexer,
45        parser::Parser,
46    };
47
48    #[test]
49    fn test_reference_to_atomic() {
50        let mut parser = Parser::new(Lexer::new_test("@u64"));
51        let result = ReferenceTy::parse(&mut parser).unwrap();
52
53        assert_eq!(result.matching_source.as_str(), "@u64");
54        assert_eq!(result.target_ty.downcast_primitive().unwrap().variant, AtomicTyVariant::U64);
55    }
56
57    #[test]
58    fn test_reference_to_a_reference_to_atomic() {
59        let mut parser = Parser::new(Lexer::new_test("@@u64"));
60        let result = ReferenceTy::parse(&mut parser).unwrap();
61
62        assert_eq!(result.matching_source.as_str(), "@@u64");
63        assert!(result.target_ty.downcast_reference().is_some());
64    }
65}