1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
use crate::parser::Parser;
use crate::syntax::entity::LazyParsedEntityDatabase;
use crate::syntax::identifier::SpannedGlobalIdentifier;
use crate::syntax::Syntax;
use lark_debug_derive::DebugWith;
use lark_entity::Entity;
use lark_error::{ErrorReported, ErrorSentinel, WithError};
use lark_intern::Untern;
use lark_span::{FileName, Span, Spanned};
use lark_string::GlobalIdentifier;
use lark_ty as ty;
use lark_ty::declaration::Declaration;
use lark_ty::TypeFamily;

#[derive(DebugWith)]
pub struct TypeReference;

impl Syntax<'parse> for TypeReference {
    type Data = ParsedTypeReference;

    fn test(&mut self, parser: &Parser<'parse>) -> bool {
        parser.test(SpannedGlobalIdentifier)
    }

    fn expect(
        &mut self,
        parser: &mut Parser<'parse>,
    ) -> Result<ParsedTypeReference, ErrorReported> {
        let identifier = parser.expect(SpannedGlobalIdentifier)?;
        Ok(ParsedTypeReference::Named(NamedTypeReference {
            identifier,
        }))
    }
}

/// Parsed form of a type.
#[derive(Copy, Clone, DebugWith)]
pub enum ParsedTypeReference {
    Named(NamedTypeReference),
    Elided(Span<FileName>),
    Error,
}

impl ParsedTypeReference {
    pub fn parse_type(
        &self,
        entity: Entity,
        db: &dyn LazyParsedEntityDatabase,
    ) -> WithError<ty::Ty<Declaration>> {
        match self {
            ParsedTypeReference::Named(named) => named.parse_type(entity, db),
            ParsedTypeReference::Elided(_span) => {
                WithError::ok(crate::type_conversion::unit_ty(db))
            }
            ParsedTypeReference::Error => WithError::ok(Declaration::error_type(&db)),
        }
    }
}

impl<Cx> ErrorSentinel<Cx> for ParsedTypeReference {
    fn error_sentinel(_cx: Cx, _report: ErrorReported) -> Self {
        ParsedTypeReference::Error
    }
}

/// Named type like `String` or (eventually) `Vec<u32>`
#[derive(Copy, Clone, DebugWith)]
pub struct NamedTypeReference {
    pub identifier: Spanned<GlobalIdentifier, FileName>,
}

impl NamedTypeReference {
    pub fn parse_type(
        &self,
        entity: Entity,
        db: &dyn LazyParsedEntityDatabase,
    ) -> WithError<ty::Ty<Declaration>> {
        match db.resolve_name(entity, self.identifier.value) {
            Some(entity) => {
                // FIXME(ndm) -- eventually, we will want some way to
                // represent types with other permissions/reprs. We'll
                // need fields on `NamedTypeReference`, and we'll need
                // to have methods for helping us adjust them
                // post-parse, or else distinct parsing combinators
                // (the former might be more convenient).
                let ty = crate::type_conversion::declaration_ty_named(
                    &db,
                    entity,
                    ty::declaration::DeclaredPermKind::Own,
                    ty::ReprKind::Direct,
                    ty::Generics::empty(),
                );
                WithError::ok(ty)
            }
            None => {
                let msg = format!("unknown type: `{}`", self.identifier.untern(&db));
                WithError::report_error(&db, msg, self.identifier.span)
            }
        }
    }
}