use crate::lexer::token::LexToken;
use crate::parser::Parser;
use crate::syntax::identifier::SpannedGlobalIdentifier;
use crate::syntax::NonEmptySyntax;
use crate::syntax::Syntax;
use crate::ParserDatabase;
use lark_collections::Seq;
use lark_debug_derive::DebugWith;
use lark_debug_with::DebugWith;
use lark_entity::Entity;
use lark_entity::EntityTables;
use lark_error::ErrorReported;
use lark_error::ErrorSentinel;
use lark_error::WithError;
use lark_hir as hir;
use lark_span::FileName;
use lark_span::Span;
use lark_span::Spanned;
use lark_string::GlobalIdentifier;
use lark_string::GlobalIdentifierTables;
use lark_string::Text;
use lark_ty as ty;
use lark_ty::declaration::Declaration;
use lark_ty::declaration::DeclarationTables;
use std::sync::Arc;
#[derive(DebugWith)]
pub struct EntitySyntax {
parent_entity: Entity,
}
impl EntitySyntax {
pub fn new(parent_entity: Entity) -> Self {
EntitySyntax { parent_entity }
}
}
impl Syntax<'parse> for EntitySyntax {
type Data = ParsedEntity;
fn test(&mut self, parser: &Parser<'_>) -> bool {
parser.test(SpannedGlobalIdentifier)
}
fn expect(&mut self, parser: &mut Parser<'_>) -> Result<Self::Data, ErrorReported> {
let macro_name = parser.expect(SpannedGlobalIdentifier)?;
log::debug!(
"EntitySyntax::parse(macro_name = {:?})",
macro_name.debug_with(parser),
);
let macro_definition = match parser.entity_macro_definitions().get(¯o_name.value) {
Some(m) => m.clone(),
None => Err(parser.report_error("no macro with this name", macro_name.span))?,
};
Ok(macro_definition.expect(parser, self.parent_entity, macro_name)?)
}
}
impl NonEmptySyntax<'parse> for EntitySyntax {}
#[derive(Clone, Debug, DebugWith, PartialEq, Eq)]
pub struct ParsedEntity {
pub entity: Entity,
pub full_span: Span<FileName>,
pub characteristic_span: Span<FileName>,
pub thunk: ParsedEntityThunk,
}
impl ParsedEntity {
crate fn new(
entity: Entity,
full_span: Span<FileName>,
characteristic_span: Span<FileName>,
thunk: ParsedEntityThunk,
) -> Self {
Self {
entity,
full_span,
characteristic_span,
thunk,
}
}
}
#[derive(Clone)]
pub struct ParsedEntityThunk {
object: Arc<dyn LazyParsedEntity + Send + Sync>,
}
impl ParsedEntityThunk {
pub fn new<T: 'static + LazyParsedEntity + Send + Sync>(object: T) -> Self {
Self {
object: Arc::new(object),
}
}
crate fn parse_children(
&self,
entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<Seq<ParsedEntity>> {
self.object.parse_children(entity, db)
}
crate fn parse_generic_declarations(
&self,
entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<Result<Arc<ty::GenericDeclarations>, ErrorReported>> {
self.object.parse_generic_declarations(entity, db)
}
crate fn parse_type(
&self,
entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<ty::Ty<Declaration>> {
self.object.parse_type(entity, db)
}
crate fn parse_signature(
&self,
entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<Result<ty::Signature<Declaration>, ErrorReported>> {
self.object.parse_signature(entity, db)
}
crate fn parse_fn_body(
&self,
entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<hir::FnBody> {
self.object.parse_fn_body(entity, db)
}
}
impl std::fmt::Debug for ParsedEntityThunk {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fmt.debug_struct("LazyParsedEntity").finish()
}
}
impl std::cmp::PartialEq for ParsedEntityThunk {
fn eq(&self, other: &Self) -> bool {
std::sync::Arc::ptr_eq(&self.object, &other.object)
}
}
impl std::cmp::Eq for ParsedEntityThunk {}
lark_debug_with::debug_fallback_impl!(ParsedEntityThunk);
pub trait LazyParsedEntity {
fn parse_children(
&self,
entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<Seq<ParsedEntity>>;
fn parse_generic_declarations(
&self,
entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<Result<Arc<ty::GenericDeclarations>, ErrorReported>>;
fn parse_type(
&self,
entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<ty::Ty<Declaration>>;
fn parse_signature(
&self,
entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<Result<ty::Signature<Declaration>, ErrorReported>>;
fn parse_fn_body(
&self,
entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<hir::FnBody>;
}
pub trait LazyParsedEntityDatabase:
AsRef<GlobalIdentifierTables> + AsRef<EntityTables> + AsRef<DeclarationTables>
{
fn resolve_name(&self, item_entity: Entity, name: GlobalIdentifier) -> Option<Entity>;
fn file_text(&self, id: FileName) -> Text;
fn file_tokens(&self, id: FileName) -> WithError<Seq<Spanned<LexToken, FileName>>>;
fn generic_declarations(
&self,
entity: Entity,
) -> WithError<Result<Arc<ty::GenericDeclarations>, ErrorReported>>;
fn ty(&self, key: Entity) -> WithError<ty::Ty<Declaration>>;
}
impl<T: ParserDatabase> LazyParsedEntityDatabase for T {
fn file_text(&self, id: FileName) -> Text {
ParserDatabase::file_text(self, id)
}
fn resolve_name(&self, item_entity: Entity, name: GlobalIdentifier) -> Option<Entity> {
ParserDatabase::resolve_name(self, item_entity, name)
}
fn file_tokens(&self, id: FileName) -> WithError<Seq<Spanned<LexToken, FileName>>> {
ParserDatabase::file_tokens(self, id)
}
fn generic_declarations(
&self,
entity: Entity,
) -> WithError<Result<Arc<ty::GenericDeclarations>, ErrorReported>> {
ParserDatabase::generic_declarations(self, entity)
}
fn ty(&self, entity: Entity) -> WithError<ty::Ty<Declaration>> {
ParserDatabase::ty(self, entity)
}
}
crate struct ErrorParsedEntity {
crate err: ErrorReported,
}
impl LazyParsedEntity for ErrorParsedEntity {
fn parse_children(
&self,
_entity: Entity,
_db: &dyn LazyParsedEntityDatabase,
) -> WithError<Seq<ParsedEntity>> {
WithError::ok(Seq::default())
}
fn parse_generic_declarations(
&self,
_entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<Result<Arc<ty::GenericDeclarations>, ErrorReported>> {
WithError::ok(ErrorSentinel::error_sentinel(db, self.err))
}
fn parse_type(
&self,
_entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<ty::Ty<Declaration>> {
WithError::ok(ErrorSentinel::error_sentinel(&db, self.err))
}
fn parse_signature(
&self,
_entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<Result<ty::Signature<Declaration>, ErrorReported>> {
WithError::ok(ErrorSentinel::error_sentinel(&db, self.err))
}
fn parse_fn_body(
&self,
_entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<hir::FnBody> {
WithError::ok(ErrorSentinel::error_sentinel(&db, self.err))
}
}
crate struct InvalidParsedEntity;
impl LazyParsedEntity for InvalidParsedEntity {
fn parse_children(
&self,
entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<Seq<ParsedEntity>> {
panic!(
"cannot invoke `parse_children` on {:?}",
entity.debug_with(db)
)
}
fn parse_generic_declarations(
&self,
entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<Result<Arc<ty::GenericDeclarations>, ErrorReported>> {
panic!(
"cannot invoke `parse_generic_declarations` on {:?}",
entity.debug_with(db)
)
}
fn parse_type(
&self,
entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<ty::Ty<Declaration>> {
panic!("cannot invoke `parse_type` on {:?}", entity.debug_with(db))
}
fn parse_signature(
&self,
entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<Result<ty::Signature<Declaration>, ErrorReported>> {
panic!(
"cannot invoke `parse_signature` on {:?}",
entity.debug_with(db)
)
}
fn parse_fn_body(
&self,
entity: Entity,
db: &dyn LazyParsedEntityDatabase,
) -> WithError<hir::FnBody> {
panic!(
"cannot invoke `parse_fn_body` on {:?}",
entity.debug_with(db)
)
}
}