use core::fmt;
use core::num::NonZeroUsize;
use crate as rune;
use crate::alloc::prelude::*;
use crate::ast::{self, Span, Spanned};
use crate::compile::{ItemId, ModId};
use crate::parse::NonZeroId;
use crate::runtime::{format, Type, TypeCheck};
use crate::Hash;
#[derive(TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[try_clone(copy)]
#[repr(transparent)]
pub(crate) struct Variable(#[try_clone(copy)] pub(crate) NonZeroId);
impl fmt::Display for Variable {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl fmt::Debug for Variable {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
#[derive(TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[try_clone(copy)]
pub(crate) enum Name<'hir> {
SelfValue,
Str(&'hir str),
}
impl fmt::Display for Name<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Name::SelfValue => write!(f, "self"),
Name::Str(name) => name.fmt(f),
}
}
}
impl fmt::Debug for Name<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Name::SelfValue => write!(f, "self"),
Name::Str(name) => name.fmt(f),
}
}
}
#[derive(Debug, TryClone, Clone, Copy, Spanned)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct Pat<'hir> {
#[rune(span)]
pub(crate) span: Span,
pub(crate) kind: PatKind<'hir>,
}
#[derive(Debug, TryClone, Clone, Copy, Spanned)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct PatBinding<'hir> {
#[rune(span)]
pub(crate) pat: Pat<'hir>,
pub(crate) names: &'hir [Variable],
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
pub(crate) enum PatPathKind<'hir> {
Kind(&'hir PatSequenceKind),
Ident(Variable),
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
pub(crate) enum PatKind<'hir> {
Ignore,
Path(&'hir PatPathKind<'hir>),
Lit(&'hir Expr<'hir>),
Sequence(&'hir PatSequence<'hir>),
Object(&'hir PatObject<'hir>),
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
pub(crate) enum PatSequenceKind {
Type {
hash: Hash,
},
BuiltInVariant {
type_check: TypeCheck,
},
Variant {
variant_hash: Hash,
enum_hash: Hash,
index: usize,
},
Anonymous {
type_check: TypeCheck,
count: usize,
is_open: bool,
},
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct PatSequence<'hir> {
pub(crate) kind: PatSequenceKind,
pub(crate) items: &'hir [Pat<'hir>],
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct PatObject<'hir> {
pub(crate) kind: PatSequenceKind,
pub(crate) bindings: &'hir [Binding<'hir>],
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) enum Binding<'hir> {
Binding(Span, &'hir str, &'hir Pat<'hir>),
Ident(Span, &'hir str, Variable),
}
impl Spanned for Binding<'_> {
fn span(&self) -> Span {
match self {
Binding::Binding(span, _, _) => *span,
Binding::Ident(span, _, _) => *span,
}
}
}
impl<'hir> Binding<'hir> {
pub(crate) fn key(&self) -> &'hir str {
match *self {
Self::Binding(_, key, _) => key,
Self::Ident(_, key, _) => key,
}
}
}
#[derive(Debug, TryClone, Clone, Copy, Spanned)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct Expr<'hir> {
#[rune(span)]
pub(crate) span: Span,
pub(crate) kind: ExprKind<'hir>,
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) enum Lit<'hir> {
Bool(bool),
Unsigned(u64),
Signed(i64),
Float(f64),
Char(char),
Str(&'hir str),
ByteStr(&'hir [u8]),
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) enum ExprKind<'hir> {
Variable(Variable),
Type(Type),
Fn(Hash),
Path,
Assign(&'hir ExprAssign<'hir>),
Loop(&'hir ExprLoop<'hir>),
For(&'hir ExprFor<'hir>),
Let(&'hir ExprLet<'hir>),
If(&'hir Conditional<'hir>),
Match(&'hir ExprMatch<'hir>),
Call(&'hir ExprCall<'hir>),
FieldAccess(&'hir ExprFieldAccess<'hir>),
Binary(&'hir ExprBinary<'hir>),
Unary(&'hir ExprUnary<'hir>),
Index(&'hir ExprIndex<'hir>),
AsyncBlock(&'hir ExprAsyncBlock<'hir>),
Block(&'hir Block<'hir>),
Break(&'hir ExprBreak<'hir>),
Continue(&'hir ExprContinue<'hir>),
Yield(Option<&'hir Expr<'hir>>),
Return(Option<&'hir Expr<'hir>>),
Await(&'hir Expr<'hir>),
Try(&'hir Expr<'hir>),
Select(&'hir ExprSelect<'hir>),
CallClosure(&'hir ExprCallClosure<'hir>),
Lit(Lit<'hir>),
Object(&'hir ExprObject<'hir>),
Tuple(&'hir ExprSeq<'hir>),
Vec(&'hir ExprSeq<'hir>),
Range(&'hir ExprRange<'hir>),
Group(&'hir Expr<'hir>),
Template(&'hir BuiltInTemplate<'hir>),
Format(&'hir BuiltInFormat<'hir>),
Const(Hash),
}
#[derive(Debug, TryClone, Clone, Copy, Spanned)]
#[try_clone(copy)]
pub(crate) struct BuiltInTemplate<'hir> {
#[rune(span)]
pub(crate) span: Span,
pub(crate) from_literal: bool,
pub(crate) exprs: &'hir [Expr<'hir>],
}
#[derive(Default, Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
pub(crate) struct BuiltInFormatSpec {
pub(crate) fill: Option<char>,
pub(crate) align: Option<format::Alignment>,
pub(crate) width: Option<NonZeroUsize>,
pub(crate) precision: Option<NonZeroUsize>,
pub(crate) flags: Option<format::Flags>,
pub(crate) format_type: Option<format::Type>,
}
#[derive(Debug, TryClone, Clone, Copy, Spanned)]
#[try_clone(copy)]
pub(crate) struct BuiltInFormat<'hir> {
pub(crate) spec: BuiltInFormatSpec,
#[rune(span)]
pub(crate) value: &'hir Expr<'hir>,
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprAssign<'hir> {
pub(crate) lhs: Expr<'hir>,
pub(crate) rhs: Expr<'hir>,
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprLoop<'hir> {
pub(crate) label: Option<&'hir str>,
pub(crate) condition: Option<&'hir Condition<'hir>>,
pub(crate) body: Block<'hir>,
#[allow(unused)]
pub(crate) drop: &'hir [Variable],
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprFor<'hir> {
pub(crate) label: Option<&'hir str>,
pub(crate) binding: PatBinding<'hir>,
pub(crate) iter: Expr<'hir>,
pub(crate) body: Block<'hir>,
#[allow(unused)]
pub(crate) drop: &'hir [Variable],
}
#[derive(Debug, TryClone, Clone, Copy, Spanned)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprLet<'hir> {
pub(crate) pat: PatBinding<'hir>,
pub(crate) expr: Expr<'hir>,
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct Conditional<'hir> {
pub(crate) branches: &'hir [ConditionalBranch<'hir>],
pub(crate) fallback: Option<&'hir Block<'hir>>,
}
#[derive(Debug, TryClone, Clone, Copy, Spanned)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ConditionalBranch<'hir> {
#[rune(span)]
pub(crate) span: Span,
pub(crate) condition: &'hir Condition<'hir>,
pub(crate) block: Block<'hir>,
#[allow(unused)]
pub(crate) drop: &'hir [Variable],
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprMatch<'hir> {
pub(crate) expr: &'hir Expr<'hir>,
pub(crate) branches: &'hir [ExprMatchBranch<'hir>],
}
#[derive(Debug, TryClone, Clone, Copy, Spanned)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprMatchBranch<'hir> {
#[rune(span)]
pub(crate) span: Span,
pub(crate) pat: PatBinding<'hir>,
pub(crate) condition: Option<&'hir Expr<'hir>>,
pub(crate) body: Expr<'hir>,
#[allow(unused)]
pub(crate) drop: &'hir [Variable],
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
pub(crate) enum Call<'hir> {
Var {
name: Variable,
},
Associated {
target: &'hir Expr<'hir>,
hash: Hash,
},
Meta {
hash: Hash,
},
Expr { expr: &'hir Expr<'hir> },
ConstFn {
from_module: ModId,
from_item: ItemId,
id: ItemId,
},
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprCall<'hir> {
pub(crate) call: Call<'hir>,
pub(crate) args: &'hir [Expr<'hir>],
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprFieldAccess<'hir> {
pub(crate) expr: Expr<'hir>,
pub(crate) expr_field: ExprField<'hir>,
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) enum ExprField<'hir> {
Index(usize),
Ident(&'hir str),
IdentGenerics(&'hir str, Hash),
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprBinary<'hir> {
pub(crate) lhs: Expr<'hir>,
pub(crate) op: ast::BinOp,
pub(crate) rhs: Expr<'hir>,
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprUnary<'hir> {
pub(crate) op: ast::UnOp,
pub(crate) expr: Expr<'hir>,
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprIndex<'hir> {
pub(crate) target: Expr<'hir>,
pub(crate) index: Expr<'hir>,
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprAsyncBlock<'hir> {
pub(crate) hash: Hash,
pub(crate) do_move: bool,
pub(crate) captures: &'hir [Variable],
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
pub(crate) struct ExprBreak<'hir> {
pub(crate) label: Option<&'hir str>,
pub(crate) expr: Option<&'hir Expr<'hir>>,
#[allow(unused)]
pub(crate) drop: &'hir [Variable],
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
pub(crate) struct ExprContinue<'hir> {
pub(crate) label: Option<&'hir str>,
#[allow(unused)]
pub(crate) drop: &'hir [Variable],
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprSelect<'hir> {
pub(crate) exprs: &'hir [Expr<'hir>],
pub(crate) branches: &'hir [ExprSelectBranch<'hir>],
pub(crate) default: Option<&'hir Expr<'hir>>,
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprSelectBranch<'hir> {
pub(crate) pat: PatBinding<'hir>,
pub(crate) body: Expr<'hir>,
#[allow(unused)]
pub(crate) drop: &'hir [Variable],
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprCallClosure<'hir> {
pub(crate) do_move: bool,
pub(crate) hash: Hash,
pub(crate) captures: &'hir [Variable],
}
#[derive(Debug, TryClone, Clone, Copy, Spanned)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprClosure<'hir> {
pub(crate) args: &'hir [FnArg<'hir>],
#[rune(span)]
pub(crate) body: &'hir Expr<'hir>,
pub(crate) captures: &'hir [Variable],
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
pub(crate) enum ExprObjectKind {
EmptyStruct { hash: Hash },
Struct { hash: Hash },
StructVariant { hash: Hash },
ExternalType { hash: Hash, args: usize },
Anonymous,
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprObject<'hir> {
pub(crate) kind: ExprObjectKind,
pub(crate) assignments: &'hir [FieldAssign<'hir>],
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct FieldAssign<'hir> {
pub(crate) key: (Span, &'hir str),
pub(crate) assign: Expr<'hir>,
pub(crate) position: Option<usize>,
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ExprSeq<'hir> {
pub(crate) items: &'hir [Expr<'hir>],
}
#[derive(Debug, TryClone, Clone, Copy)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) enum ExprRange<'hir> {
RangeFrom { start: Expr<'hir> },
RangeFull,
RangeInclusive { start: Expr<'hir>, end: Expr<'hir> },
RangeToInclusive { end: Expr<'hir> },
RangeTo { end: Expr<'hir> },
Range { start: Expr<'hir>, end: Expr<'hir> },
}
#[derive(Debug, TryClone, Clone, Copy, Spanned)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) enum Condition<'hir> {
Expr(&'hir Expr<'hir>),
ExprLet(&'hir ExprLet<'hir>),
}
impl Condition<'_> {
pub(crate) fn count(&self) -> Option<usize> {
match self {
Condition::Expr(_) => None,
Condition::ExprLet(hir) => Some(hir.pat.names.len()),
}
}
}
#[derive(Debug, TryClone, Clone, Copy, Spanned)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct ItemFn<'hir> {
#[rune(span)]
pub(crate) span: Span,
pub(crate) args: &'hir [FnArg<'hir>],
pub(crate) body: Block<'hir>,
}
#[derive(Debug, TryClone, Clone, Copy, Spanned)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) enum FnArg<'hir> {
SelfValue(#[rune(span)] Span, Variable),
Pat(&'hir PatBinding<'hir>),
}
#[derive(Debug, TryClone, Clone, Copy, Spanned)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct Block<'hir> {
#[rune(span)]
pub(crate) span: Span,
pub(crate) label: Option<&'hir str>,
pub(crate) statements: &'hir [Stmt<'hir>],
pub(crate) value: Option<&'hir Expr<'hir>>,
#[allow(unused)]
pub(crate) drop: &'hir [Variable],
}
#[derive(Debug, TryClone, Clone, Copy, Spanned)]
#[try_clone(copy)]
pub(crate) struct AsyncBlock<'hir> {
#[rune(span)]
pub(crate) block: &'hir Block<'hir>,
pub(crate) captures: &'hir [Variable],
}
#[derive(Debug, TryClone, Clone, Copy, Spanned)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) enum Stmt<'hir> {
Local(&'hir Local<'hir>),
Expr(&'hir Expr<'hir>),
}
#[derive(Debug, TryClone, Clone, Copy, Spanned)]
#[try_clone(copy)]
#[non_exhaustive]
pub(crate) struct Local<'hir> {
#[rune(span)]
pub(crate) span: Span,
pub(crate) pat: PatBinding<'hir>,
pub(crate) expr: Expr<'hir>,
}