mod interface;
pub use self::interface::{
ComponentExport, ComponentId, ComponentInterface, ModuleExport, ModuleInterface,
};
use crate::{
Ident, IdentAttr, Op, OpParser, OpPrinter, Operation, RegionKind, RegionKindInterface, Symbol,
SymbolManager, SymbolManagerMut, SymbolMap, SymbolRef, SymbolTable, SymbolUseList,
UnsafeIntrusiveEntityRef, Usable, Visibility,
derive::operation,
dialects::builtin::{BuiltinDialect, attributes::VisibilityAttr},
interner,
print::AsmPrinter,
traits::{
GraphRegionNoTerminator, HasOnlyGraphRegion, IsolatedFromAbove, NoRegionArguments,
NoTerminator, SingleBlock, SingleRegion,
},
version::VersionAttr,
};
pub type ComponentRef = UnsafeIntrusiveEntityRef<Component>;
#[operation(
dialect = BuiltinDialect,
traits(
SingleRegion,
SingleBlock,
NoRegionArguments,
NoTerminator,
HasOnlyGraphRegion,
GraphRegionNoTerminator,
IsolatedFromAbove,
),
implements(RegionKindInterface, SymbolTable, Symbol, OpPrinter)
)]
pub struct Component {
#[attr]
namespace: IdentAttr,
#[attr]
name: IdentAttr,
#[attr]
version: VersionAttr,
#[attr]
#[default]
visibility: VisibilityAttr,
#[region]
body: RegionRef,
#[default]
symbols: SymbolMap,
#[default]
uses: SymbolUseList,
}
impl OpPrinter for Component {
fn print(&self, printer: &mut AsmPrinter<'_>) {
use alloc::string::ToString;
printer.print_space();
printer.print_keyword(self.get_visibility().as_str());
printer.print_space();
printer.print_symbol_name(interner::Symbol::intern(self.id().to_string()));
printer.print_space();
printer.print_region(&self.body());
}
}
impl OpParser for Component {
fn parse(
state: &mut crate::OperationState,
parser: &mut dyn crate::OpAsmParser<'_>,
) -> crate::ParseResult {
use alloc::{format, string::ToString, vec};
use crate::{
diagnostics::{LabeledSpan, RelatedError, Report, Severity, miette::diagnostic},
parse::{ParserError, Token},
};
let context = parser.context_rc();
let visibility = parser
.parse_keyword_from(&[
Token::BareIdent("public"),
Token::BareIdent("private"),
Token::BareIdent("internal"),
])?
.into_inner()
.parse::<Visibility>()
.expect("one or more of these visibilities are no longer valid");
state
.add_attribute("visibility", context.create_attribute::<VisibilityAttr, _>(visibility));
let name = parser.parse_symbol_name()?;
let name_span = name.span;
let component_id = name.as_str().parse::<ComponentId>().map_err(|err| {
ParserError::Report(RelatedError::new(Report::from(diagnostic!(
severity = Severity::Error,
labels = vec![LabeledSpan::at(name_span, err.to_string())],
"invalid component name"
))))
})?;
state.add_attribute(
"namespace",
context.create_attribute::<IdentAttr, _>(Ident::new(component_id.namespace, name_span)),
);
state.add_attribute(
"name",
context.create_attribute::<IdentAttr, _>(Ident::new(component_id.name, name_span)),
);
state.add_attribute(
"version",
context.create_attribute::<VersionAttr, _>(component_id.version),
);
let region = parser.context().create_region();
parser.parse_region(region, &[], true)?;
state.add_region(region);
Ok(())
}
}
impl midenc_session::Emit for Component {
fn name(&self) -> Option<midenc_hir_symbol::Symbol> {
Some(self.name().as_symbol())
}
fn output_type(&self, _mode: midenc_session::OutputMode) -> midenc_session::OutputType {
midenc_session::OutputType::Hir
}
fn write_to<W: midenc_session::Writer>(
&self,
mut writer: W,
_mode: midenc_session::OutputMode,
_session: &midenc_session::Session,
) -> anyhow::Result<()> {
use crate::OpPrinter;
let flags = crate::OpPrintingFlags::default();
let mut printer = AsmPrinter::new(self.as_operation().context_rc(), &flags);
<Self as OpPrinter>::print(self, &mut printer);
writer.write_fmt(format_args!("{}", printer.finish()))
}
}
impl RegionKindInterface for Component {
#[inline(always)]
fn kind(&self) -> RegionKind {
RegionKind::Graph
}
}
impl Usable for Component {
type Use = crate::SymbolUse;
#[inline(always)]
fn uses(&self) -> &SymbolUseList {
&self.uses
}
#[inline(always)]
fn uses_mut(&mut self) -> &mut SymbolUseList {
&mut self.uses
}
}
impl Symbol for Component {
#[inline(always)]
fn as_symbol_operation(&self) -> &Operation {
&self.op
}
#[inline(always)]
fn as_symbol_operation_mut(&mut self) -> &mut Operation {
&mut self.op
}
fn name(&self) -> interner::Symbol {
let id = ComponentId {
namespace: self.get_namespace().as_symbol(),
name: self.get_name().as_symbol(),
version: self.get_version().clone(),
};
interner::Symbol::intern(id)
}
fn set_name(&mut self, name: interner::Symbol) {
let ComponentId {
name,
namespace,
version,
} = name.as_str().parse::<ComponentId>().expect("invalid component identifier");
self.name_mut().name = name;
self.namespace_mut().name = namespace;
*self.get_version_mut() = version;
}
fn visibility(&self) -> Visibility {
*self.get_visibility()
}
fn set_visibility(&mut self, visibility: Visibility) {
*self.get_visibility_mut() = visibility;
}
}
impl SymbolTable for Component {
#[inline(always)]
fn as_symbol_table_operation(&self) -> &Operation {
&self.op
}
#[inline(always)]
fn as_symbol_table_operation_mut(&mut self) -> &mut Operation {
&mut self.op
}
fn symbol_manager(&self) -> SymbolManager<'_> {
SymbolManager::new(&self.op, crate::Symbols::Borrowed(&self.symbols))
}
fn symbol_manager_mut(&mut self) -> SymbolManagerMut<'_> {
SymbolManagerMut::new(&mut self.op, crate::SymbolsMut::Borrowed(&mut self.symbols))
}
#[inline]
fn get(&self, name: interner::Symbol) -> Option<SymbolRef> {
self.symbols.get(name)
}
}
impl Component {
#[inline]
pub fn id(&self) -> ComponentId {
ComponentId::from(self)
}
#[inline(always)]
pub fn as_component_ref(&self) -> ComponentRef {
unsafe { ComponentRef::from_raw(self) }
}
}