use vize_l0::Span;
use crate::op::{OpId, RegionId};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OperandRole {
Tag,
Namespace,
Attribute,
Text,
Comment,
BindingKind,
Name,
Value,
Modifier,
Condition,
ForSource,
ForValue,
ForKey,
ForIndex,
ModelRead,
ModelWrite,
ModelAttribute,
Params,
}
impl OperandRole {
#[must_use]
pub const fn accepts_target(self, present: bool) -> bool {
match self {
Self::BindingKind
| Self::Value
| Self::Modifier
| Self::ModelRead
| Self::ModelWrite
| Self::ModelAttribute
| Self::Params => present,
Self::Tag | Self::Name => true,
Self::Namespace
| Self::Attribute
| Self::Text
| Self::Comment
| Self::Condition
| Self::ForSource
| Self::ForValue
| Self::ForKey
| Self::ForIndex => !present,
}
}
pub const ALL: [Self; 18] = [
Self::Tag,
Self::Namespace,
Self::Attribute,
Self::Text,
Self::Comment,
Self::BindingKind,
Self::Name,
Self::Value,
Self::Modifier,
Self::Condition,
Self::ForSource,
Self::ForValue,
Self::ForKey,
Self::ForIndex,
Self::ModelRead,
Self::ModelWrite,
Self::ModelAttribute,
Self::Params,
];
#[must_use]
pub fn parse(text: &str) -> Option<Self> {
Self::ALL.into_iter().find(|role| role.as_str() == text)
}
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::Tag => "tag",
Self::Namespace => "namespace",
Self::Attribute => "attribute",
Self::Text => "text",
Self::Comment => "comment",
Self::BindingKind => "binding-kind",
Self::Name => "name",
Self::Value => "value",
Self::Modifier => "modifier",
Self::Condition => "condition",
Self::ForSource => "for-source",
Self::ForValue => "for-value",
Self::ForKey => "for-key",
Self::ForIndex => "for-index",
Self::ModelRead => "model-read",
Self::ModelWrite => "model-write",
Self::ModelAttribute => "model-attribute",
Self::Params => "params",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ValueKind {
Absent,
Literal,
Js,
Opaque,
Foreign,
Filter,
NativeHandler,
}
impl ValueKind {
pub const ALL: [Self; 7] = [
Self::Absent,
Self::Literal,
Self::Js,
Self::Opaque,
Self::Foreign,
Self::Filter,
Self::NativeHandler,
];
#[must_use]
pub fn parse(text: &str) -> Option<Self> {
Self::ALL.into_iter().find(|kind| kind.as_str() == text)
}
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::Absent => "absent",
Self::Literal => "literal",
Self::Js => "js",
Self::Opaque => "opaque",
Self::Foreign => "foreign",
Self::Filter => "vue.filter",
Self::NativeHandler => "native.handler",
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct OperandValue<'a> {
pub kind: ValueKind,
pub native_handler: Option<vize_l2::op::HandlerId>,
pub text: &'a str,
pub qualifier: &'a str,
pub span: Span,
}
impl OperandValue<'_> {
#[must_use]
pub fn is_well_formed(&self) -> bool {
self.span.start <= self.span.end
&& (self.native_handler.is_some() == (self.kind == ValueKind::NativeHandler))
&& (self.kind != ValueKind::NativeHandler || self.text.is_empty())
&& (self.kind != ValueKind::Absent || self.text.is_empty())
&& match self.kind {
ValueKind::Opaque | ValueKind::Foreign => !self.qualifier.is_empty(),
_ => self.qualifier.is_empty(),
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Operand<'a> {
pub op: OpId,
pub role: OperandRole,
pub target: Option<OpId>,
pub region: Option<RegionId>,
pub name: Option<&'a str>,
pub value: OperandValue<'a>,
}
const _: () = assert!(!core::mem::needs_drop::<Operand<'static>>());
#[cfg(target_pointer_width = "64")]
const _: () = assert!(core::mem::size_of::<OperandValue<'_>>() == 48);