use crate::{
builtin::Builtin,
symbol::{Symbol, SymbolDef},
syntax::*,
};
use microcad_lang_base::{Refer, SrcRef};
pub trait Doc {
fn doc(&self) -> DocBlock {
DocBlock::merge(&self.outer_doc(), &self.inner_doc())
}
fn inner_doc(&self) -> DocBlock {
DocBlock::default()
}
fn outer_doc(&self) -> DocBlock {
DocBlock::default()
}
}
impl Doc for DocBlock {
fn doc(&self) -> DocBlock {
self.clone()
}
}
impl Doc for InitDefinition {
fn outer_doc(&self) -> DocBlock {
self.doc.as_ref().cloned().unwrap_or_default()
}
fn inner_doc(&self) -> DocBlock {
self.body.inner_doc()
}
}
impl Doc for StatementList {
fn inner_doc(&self) -> DocBlock {
if self.is_empty() {
DocBlock::default()
} else {
let src_ref = SrcRef::merge_all(self.iter());
DocBlock(Refer::new(
self.iter()
.filter_map(|s| match s {
Statement::InnerDocComment(doc) => Some(doc.0.value.clone()),
_ => None,
})
.collect::<Vec<_>>(),
src_ref,
))
}
}
}
impl Doc for Body {
fn inner_doc(&self) -> DocBlock {
self.statements.inner_doc()
}
}
impl Doc for ModuleDefinition {
fn outer_doc(&self) -> DocBlock {
self.doc.as_ref().cloned().unwrap_or_default()
}
fn inner_doc(&self) -> DocBlock {
self.body
.as_ref()
.map(|body| body.inner_doc())
.unwrap_or_default()
}
}
impl Doc for FunctionDefinition {
fn outer_doc(&self) -> DocBlock {
self.doc.as_ref().cloned().unwrap_or_default()
}
fn inner_doc(&self) -> DocBlock {
self.body.inner_doc()
}
}
impl Doc for WorkbenchDefinition {
fn outer_doc(&self) -> DocBlock {
self.doc.as_ref().cloned().unwrap_or_default()
}
fn inner_doc(&self) -> DocBlock {
self.body.inner_doc()
}
}
impl Doc for SourceFile {
fn inner_doc(&self) -> DocBlock {
self.statements.inner_doc()
}
}
impl Doc for Assignment {
fn outer_doc(&self) -> DocBlock {
self.doc.as_ref().cloned().unwrap_or_default()
}
}
impl Doc for Builtin {
fn outer_doc(&self) -> DocBlock {
match self {
Builtin::Function(builtin_function) => builtin_function.doc.clone(),
Builtin::Workbench(builtin_workbench) => builtin_workbench.doc.clone(),
Builtin::Constant(builtin_constant) => builtin_constant.doc.clone(),
}
.unwrap_or_default()
}
}
impl Doc for SymbolDef {
fn inner_doc(&self) -> DocBlock {
match &self {
SymbolDef::SourceFile(source_file) => source_file.inner_doc(),
SymbolDef::Module(module_definition) => module_definition.inner_doc(),
SymbolDef::Workbench(workbench_definition) => workbench_definition.inner_doc(),
SymbolDef::Function(function_definition) => function_definition.inner_doc(),
_ => DocBlock::default(),
}
}
fn outer_doc(&self) -> DocBlock {
match &self {
SymbolDef::Module(module_definition) => module_definition.outer_doc(),
SymbolDef::Workbench(workbench_definition) => workbench_definition.outer_doc(),
SymbolDef::Function(function_definition) => function_definition.outer_doc(),
SymbolDef::Assignment(assignment) => assignment.outer_doc(),
SymbolDef::Builtin(builtin) => builtin.outer_doc(),
_ => DocBlock::default(),
}
}
}
impl Doc for Symbol {
fn inner_doc(&self) -> DocBlock {
self.with_def(|def| def.inner_doc())
}
fn outer_doc(&self) -> DocBlock {
self.with_def(|def| def.outer_doc())
}
}