mod dump;
use wolf_span::Span;
pub use dump::dump;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct NodeId(pub u32);
#[derive(Clone, Debug, PartialEq)]
pub struct Ident {
pub name: String,
pub span: Span,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Path {
pub segments: Vec<Ident>,
pub span: Span,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Doc {
pub text: String,
pub inner: bool,
pub span: Span,
}
#[derive(Clone, Debug, PartialEq)]
pub struct File {
pub docs: Vec<Doc>,
pub module: Option<Path>,
pub sections: Vec<Section>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum SectionKind {
Imports,
Extern,
Config,
Types,
Interfaces,
Impl,
Main,
Functions,
Tests,
}
impl SectionKind {
pub const ALL: [SectionKind; 9] = [
SectionKind::Imports,
SectionKind::Extern,
SectionKind::Config,
SectionKind::Types,
SectionKind::Interfaces,
SectionKind::Impl,
SectionKind::Main,
SectionKind::Functions,
SectionKind::Tests,
];
pub fn name(self) -> &'static str {
match self {
SectionKind::Imports => "imports",
SectionKind::Extern => "extern",
SectionKind::Config => "config",
SectionKind::Types => "types",
SectionKind::Interfaces => "interfaces",
SectionKind::Impl => "impl",
SectionKind::Main => "main",
SectionKind::Functions => "functions",
SectionKind::Tests => "tests",
}
}
pub fn from_name(name: &str) -> Option<SectionKind> {
SectionKind::ALL
.into_iter()
.find(|kind| kind.name() == name)
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Section {
pub kind: SectionKind,
pub name_span: Span,
pub span: Span,
pub items: Vec<Item>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Item {
pub docs: Vec<Doc>,
pub kind: ItemKind,
pub span: Span,
}
#[derive(Clone, Debug, PartialEq)]
pub enum ItemKind {
Import(Import),
ExternTarget(ExternTarget),
Config(ConfigEntry),
Struct(StructDecl),
Enum(EnumDecl),
Alias(AliasDecl),
IntrinsicType(IntrinsicTypeDecl),
Interface(InterfaceDecl),
Impl(ImplBlock),
Fn(FnDecl),
Test(TestDecl),
}
impl ItemKind {
pub fn home(&self) -> SectionKind {
match self {
ItemKind::Import(_) => SectionKind::Imports,
ItemKind::ExternTarget(_) => SectionKind::Extern,
ItemKind::Config(_) => SectionKind::Config,
ItemKind::Struct(_)
| ItemKind::Enum(_)
| ItemKind::Alias(_)
| ItemKind::IntrinsicType(_) => SectionKind::Types,
ItemKind::Interface(_) => SectionKind::Interfaces,
ItemKind::Impl(_) => SectionKind::Impl,
ItemKind::Fn(_) => SectionKind::Functions,
ItemKind::Test(_) => SectionKind::Tests,
}
}
pub fn describe(&self) -> &'static str {
match self {
ItemKind::Import(_) => "import",
ItemKind::ExternTarget(_) => "extern block",
ItemKind::Config(_) => "constant",
ItemKind::Struct(_) => "`struct`",
ItemKind::Enum(_) => "`enum`",
ItemKind::Alias(_) => "type alias",
ItemKind::IntrinsicType(_) => "`intrinsic type`",
ItemKind::Interface(_) => "`interface`",
ItemKind::Impl(_) => "`impl` block",
ItemKind::Fn(_) => "`fn`",
ItemKind::Test(_) => "test",
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Import {
pub public: bool,
pub path: Path,
pub alias: Option<Ident>,
pub names: Option<Vec<ImportName>>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct ImportName {
pub name: Ident,
pub alias: Option<Ident>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct ExternTarget {
pub target: Ident,
pub decls: Vec<ExternDecl>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct ExternDecl {
pub docs: Vec<Doc>,
pub public: bool,
pub kind: ExternDeclKind,
pub from: StrLit,
pub span: Span,
pub native: Option<NativeSig>,
pub native_fields: Vec<(String, NativeTy)>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct NativeSig {
pub params: Vec<NativeTy>,
pub ret: NativeTy,
}
#[derive(Clone, Debug, PartialEq)]
pub enum NativeTy {
Int(String),
Float(String),
Bool,
Str,
String,
RefString,
Slice(Box<NativeTy>),
Vec(Box<NativeTy>),
RefVec(Box<NativeTy>),
Map {
kind: String,
by_ref: bool,
key: Box<NativeTy>,
value: Box<NativeTy>,
},
Option(Box<NativeTy>),
Result(Box<NativeTy>),
Unit,
Named {
name: String,
by_ref: bool,
},
Callback,
Record {
name: String,
by_ref: bool,
},
}
#[derive(Clone, Debug, PartialEq)]
pub enum ExternDeclKind {
Fn(FnSig),
Type(Ident),
Struct(Ident),
}
#[derive(Clone, Debug, PartialEq)]
pub struct StrLit {
pub value: String,
pub span: Span,
}
#[derive(Clone, Debug, PartialEq)]
pub struct ConfigEntry {
pub public: bool,
pub name: Ident,
pub ty: Ty,
pub value: Expr,
}
#[derive(Clone, Debug, PartialEq)]
pub struct GenericParam {
pub name: Ident,
pub bounds: Vec<Ty>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct StructDecl {
pub public: bool,
pub name: Ident,
pub generics: Vec<GenericParam>,
pub fields: Vec<Field>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Field {
pub docs: Vec<Doc>,
pub public: bool,
pub name: Ident,
pub ty: Ty,
pub span: Span,
}
#[derive(Clone, Debug, PartialEq)]
pub struct EnumDecl {
pub public: bool,
pub name: Ident,
pub generics: Vec<GenericParam>,
pub variants: Vec<Variant>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Variant {
pub docs: Vec<Doc>,
pub name: Ident,
pub payload: VariantPayload,
pub span: Span,
}
#[derive(Clone, Debug, PartialEq)]
pub enum VariantPayload {
None,
Tuple(Vec<Ty>),
Struct(Vec<Field>),
}
#[derive(Clone, Debug, PartialEq)]
pub struct AliasDecl {
pub public: bool,
pub name: Ident,
pub generics: Vec<GenericParam>,
pub ty: Ty,
}
#[derive(Clone, Debug, PartialEq)]
pub struct IntrinsicTypeDecl {
pub public: bool,
pub name: Ident,
pub generics: Vec<GenericParam>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct InterfaceDecl {
pub public: bool,
pub name: Ident,
pub generics: Vec<GenericParam>,
pub methods: Vec<MethodSig>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct MethodSig {
pub docs: Vec<Doc>,
pub sig: FnSig,
}
#[derive(Clone, Debug, PartialEq)]
pub struct ImplBlock {
pub type_name: Ident,
pub generics: Vec<GenericParam>,
pub interface: Option<Ty>,
pub methods: Vec<Method>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Method {
pub docs: Vec<Doc>,
pub decl: FnDecl,
pub span: Span,
}
#[derive(Clone, Debug, PartialEq)]
pub struct FnDecl {
pub public: bool,
pub intrinsic: bool,
pub sig: FnSig,
pub body: Option<Block>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct FnSig {
pub name: Ident,
pub generics: Vec<GenericParam>,
pub params: Vec<Param>,
pub ret: Option<Ty>,
pub span: Span,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Mode {
Read,
Mut,
Own,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Param {
pub mode: Mode,
pub kind: ParamKind,
pub span: Span,
}
#[derive(Clone, Debug, PartialEq)]
pub enum ParamKind {
SelfParam,
Named {
name: Ident,
ty: Ty,
},
}
#[derive(Clone, Debug, PartialEq)]
pub struct TestDecl {
pub name: StrLit,
pub body: Block,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Ty {
pub id: NodeId,
pub kind: TyKind,
pub span: Span,
}
#[derive(Clone, Debug, PartialEq)]
pub enum TyKind {
Path {
path: Path,
args: Vec<Ty>,
},
Fn {
params: Vec<(Mode, Ty)>,
ret: Option<Box<Ty>>,
},
SelfType,
Error,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Block {
pub stmts: Vec<Stmt>,
pub span: Span,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Stmt {
pub kind: StmtKind,
pub span: Span,
}
#[derive(Clone, Debug, PartialEq)]
pub enum StmtKind {
Let {
mutable: bool,
name: Option<Ident>,
ty: Option<Ty>,
value: Expr,
},
LetPattern {
mutable: bool,
pattern: Pat,
value: Expr,
},
Assign {
target: Expr,
op: AssignOp,
value: Expr,
},
While {
label: Option<Ident>,
cond: Expr,
body: Block,
},
WhileLet {
label: Option<Ident>,
pattern: Pat,
mode: Mode,
value: Expr,
body: Block,
},
For {
label: Option<Ident>,
var: Ident,
iter: ForIter,
body: Block,
},
Expr(Expr),
}
#[derive(Clone, Debug, PartialEq)]
pub enum ForIter {
Collection {
mode: Mode,
expr: Expr,
},
Range {
start: Expr,
end: Expr,
inclusive: bool,
},
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum AssignOp {
Assign,
Add,
Sub,
Mul,
Div,
Rem,
BitAnd,
BitOr,
BitXor,
Shl,
Shr,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Expr {
pub id: NodeId,
pub kind: ExprKind,
pub span: Span,
}
#[derive(Clone, Debug, PartialEq)]
pub enum ExprKind {
Int(u64),
Float(f64),
Str(String),
FStr(Vec<FStrPart>),
Bool(bool),
Unit,
Name(Ident),
SelfValue,
SelfType,
Paren(Box<Expr>),
List(Vec<Expr>),
Map(Vec<(Expr, Expr)>),
StructLit {
path: Path,
type_args: Vec<Ty>,
fields: Vec<FieldInit>,
base: Option<Box<Expr>>,
},
Field {
base: Box<Expr>,
name: Ident,
},
TypeArgs {
base: Box<Expr>,
args: Vec<Ty>,
},
Call {
callee: Box<Expr>,
args: Vec<Arg>,
},
Index {
base: Box<Expr>,
index: Box<Expr>,
},
Slice {
base: Box<Expr>,
start: Option<Box<Expr>>,
end: Option<Box<Expr>>,
inclusive: bool,
},
Try(Box<Expr>),
Unary {
op: UnaryOp,
operand: Box<Expr>,
},
Binary {
op: BinaryOp,
lhs: Box<Expr>,
rhs: Box<Expr>,
},
Closure {
params: Vec<ClosureParam>,
ret: Option<Ty>,
body: Box<Expr>,
},
Block(Block),
If {
cond: Box<Expr>,
then: Block,
otherwise: Option<Box<Expr>>,
},
IfLet {
pattern: Pat,
mode: Mode,
value: Box<Expr>,
then: Block,
otherwise: Option<Box<Expr>>,
},
Loop {
label: Option<Ident>,
body: Block,
},
Match {
mode: Mode,
scrutinee: Box<Expr>,
arms: Vec<Arm>,
},
Return(Option<Box<Expr>>),
Break {
label: Option<Ident>,
value: Option<Box<Expr>>,
},
Continue {
label: Option<Ident>,
},
Error,
}
#[derive(Clone, Debug, PartialEq)]
pub enum FStrPart {
Text(String),
Expr(Expr),
}
#[derive(Clone, Debug, PartialEq)]
pub struct FieldInit {
pub id: NodeId,
pub name: Ident,
pub value: Option<Expr>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Arg {
pub mode: Mode,
pub value: Expr,
}
#[derive(Clone, Debug, PartialEq)]
pub struct ClosureParam {
pub name: Ident,
pub ty: Option<Ty>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Arm {
pub pattern: Pat,
pub guard: Option<Expr>,
pub body: Expr,
pub span: Span,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum UnaryOp {
Neg,
Not,
BitNot,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum BinaryOp {
Mul,
Div,
Rem,
Add,
Sub,
Shl,
Shr,
BitAnd,
BitXor,
BitOr,
Eq,
NotEq,
Lt,
Le,
Gt,
Ge,
And,
Or,
}
impl BinaryOp {
pub fn symbol(self) -> &'static str {
match self {
BinaryOp::Mul => "*",
BinaryOp::Div => "/",
BinaryOp::Rem => "%",
BinaryOp::Add => "+",
BinaryOp::Sub => "-",
BinaryOp::Shl => "<<",
BinaryOp::Shr => ">>",
BinaryOp::BitAnd => "&",
BinaryOp::BitXor => "^",
BinaryOp::BitOr => "|",
BinaryOp::Eq => "==",
BinaryOp::NotEq => "!=",
BinaryOp::Lt => "<",
BinaryOp::Le => "<=",
BinaryOp::Gt => ">",
BinaryOp::Ge => ">=",
BinaryOp::And => "&&",
BinaryOp::Or => "||",
}
}
pub fn is_comparison(self) -> bool {
matches!(
self,
BinaryOp::Eq
| BinaryOp::NotEq
| BinaryOp::Lt
| BinaryOp::Le
| BinaryOp::Gt
| BinaryOp::Ge
)
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Pat {
pub id: NodeId,
pub kind: PatKind,
pub span: Span,
}
#[derive(Clone, Debug, PartialEq)]
pub enum PatKind {
Wild,
Name(Ident),
Int {
negative: bool,
value: u64,
},
Str(String),
Bool(bool),
Path(Path),
Tuple {
path: Path,
items: Vec<Pat>,
},
Struct {
path: Path,
fields: Vec<FieldPat>,
rest: bool,
},
Or(Vec<Pat>),
Error,
}
#[derive(Clone, Debug, PartialEq)]
pub struct FieldPat {
pub id: NodeId,
pub name: Ident,
pub pat: Option<Pat>,
}