use crate::span::Span;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Ident {
pub name: String,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PathStart {
Crate,
SelfMod,
Super,
None,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Path {
pub leading: PathStart,
pub segments: Vec<Ident>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TypeExpr {
pub path: Option<Path>,
pub name: Ident,
pub args: Vec<TypeExpr>,
pub span: Span,
}
impl TypeExpr {
pub fn display_name(&self) -> String {
let mut out = String::new();
if let Some(path) = &self.path {
match path.leading {
PathStart::Crate => out.push_str("crate::"),
PathStart::SelfMod => out.push_str("self::"),
PathStart::Super => out.push_str("super::"),
PathStart::None => {}
}
for segment in &path.segments {
out.push_str(&segment.name);
out.push_str("::");
}
}
out.push_str(&self.name.name);
if !self.args.is_empty() {
out.push('<');
for (i, arg) in self.args.iter().enumerate() {
if i > 0 {
out.push_str(", ");
}
out.push_str(&arg.display_name());
}
out.push('>');
}
out
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Attribute {
pub name: Ident,
pub arg: Option<AttrArg>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AttrArg {
Str(String),
Int {
text: String,
negative: bool,
},
Float {
text: String,
negative: bool,
},
Bool(bool),
Other,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Program {
pub items: Vec<Item>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Item {
Function(Function),
Struct(StructDecl),
Enum(EnumDecl),
Impl(ImplBlock),
Mod(ModDecl),
Use(UseDecl),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SelfMode {
None,
Shared,
Mutable,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Function {
pub attrs: Vec<Attribute>,
pub name: Ident,
pub is_pub: bool,
pub is_async: bool,
pub self_mode: SelfMode,
pub self_span: Option<Span>,
pub params: Vec<Param>,
pub return_type: Option<TypeExpr>,
pub body: Block,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Param {
pub name: Ident,
pub mutable: bool,
pub ty: TypeExpr,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct StructDecl {
pub attrs: Vec<Attribute>,
pub name: Ident,
pub is_pub: bool,
pub fields: Vec<FieldDecl>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct FieldDecl {
pub attrs: Vec<Attribute>,
pub name: Ident,
pub ty: TypeExpr,
pub is_pub: bool,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct EnumDecl {
pub attrs: Vec<Attribute>,
pub name: Ident,
pub is_pub: bool,
pub variants: Vec<EnumVariant>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct EnumVariant {
pub attrs: Vec<Attribute>,
pub name: Ident,
pub fields: VariantFields,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub enum VariantFields {
Unit,
Tuple(Vec<TypeExpr>),
Named(Vec<VariantField>),
}
#[derive(Debug, Clone, PartialEq)]
pub struct VariantField {
pub attrs: Vec<Attribute>,
pub name: Ident,
pub ty: TypeExpr,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ImplBlock {
pub attrs: Vec<Attribute>,
pub type_name: Ident,
pub functions: Vec<Function>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ModDecl {
pub attrs: Vec<Attribute>,
pub name: Ident,
pub is_pub: bool,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct UseDecl {
pub attrs: Vec<Attribute>,
pub path: Path,
pub alias: Option<Ident>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Stmt {
Let {
name: Ident,
mutable: bool,
ty: Option<TypeExpr>,
value: Expr,
span: Span,
},
Assign {
target: Expr,
value: Expr,
span: Span,
},
Expr {
expr: Expr,
span: Span,
has_semi: bool,
},
Return {
value: Option<Expr>,
span: Span,
},
While {
cond: Expr,
body: Block,
span: Span,
},
WhileLet {
pattern: Pattern,
value: Expr,
body: Block,
span: Span,
},
For {
var: Ident,
head: ForHead,
body: Block,
span: Span,
},
Break {
span: Span,
},
Continue {
span: Span,
},
}
#[derive(Debug, Clone, PartialEq)]
pub enum ForHead {
Range {
start: Box<Expr>,
end: Box<Expr>,
inclusive: bool,
},
Expr(Box<Expr>),
}
#[derive(Debug, Clone, PartialEq)]
pub struct Block {
pub stmts: Vec<Stmt>,
pub tail: Option<Box<Expr>>,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnaryOp {
Neg,
Not,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinaryOp {
Or,
And,
Eq,
Ne,
Lt,
Le,
Gt,
Ge,
Add,
Sub,
Mul,
Div,
Rem,
}
impl BinaryOp {
pub fn as_str(self) -> &'static str {
match self {
BinaryOp::Or => "||",
BinaryOp::And => "&&",
BinaryOp::Eq => "==",
BinaryOp::Ne => "!=",
BinaryOp::Lt => "<",
BinaryOp::Le => "<=",
BinaryOp::Gt => ">",
BinaryOp::Ge => ">=",
BinaryOp::Add => "+",
BinaryOp::Sub => "-",
BinaryOp::Mul => "*",
BinaryOp::Div => "/",
BinaryOp::Rem => "%",
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Expr {
pub kind: ExprKind,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ExprKind {
Integer(String),
Float(String),
Bool(bool),
String(String),
Path {
path: Option<Path>,
name: Ident,
},
Unary {
op: UnaryOp,
operand: Box<Expr>,
},
Binary {
op: BinaryOp,
lhs: Box<Expr>,
rhs: Box<Expr>,
},
Call {
callee: Box<Expr>,
args: Vec<Expr>,
},
Field {
base: Box<Expr>,
name: Ident,
},
MethodCall {
receiver: Box<Expr>,
method: Ident,
args: Vec<Expr>,
},
Index {
base: Box<Expr>,
index: Box<Expr>,
},
Try {
operand: Box<Expr>,
},
Await(Box<Expr>),
Match {
scrutinee: Box<Expr>,
arms: Vec<MatchArm>,
},
VecLit(Vec<Expr>),
StructLit {
path: Option<Path>,
name: Ident,
fields: Vec<(Ident, Expr)>,
},
Block(Block),
If {
cond: Box<Expr>,
then: Block,
else_: Option<Block>,
},
IfLet {
pattern: Pattern,
value: Box<Expr>,
then: Block,
else_: Option<Block>,
span: Span,
},
Closure {
params: Vec<Ident>,
body: Box<Expr>,
span: Span,
},
Cast {
expr: Box<Expr>,
ty: TypeExpr,
span: Span,
},
Intrinsic {
name: Ident,
format: (String, Span),
args: Vec<Expr>,
},
}
#[derive(Debug, Clone, PartialEq)]
pub struct MatchArm {
pub pattern: Pattern,
pub body: Expr,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Pattern {
Wildcard(Span),
Name(Ident),
Variant {
path: Option<Path>,
name: Ident,
fields: Vec<Pattern>,
span: Span,
},
Struct {
path: Option<Path>,
name: Ident,
fields: Vec<(Ident, Pattern)>,
span: Span,
},
Literal(Literal, Span),
Range {
start: Literal,
end: Literal,
span: Span,
},
}
impl Pattern {
pub fn span(&self) -> Span {
match self {
Pattern::Wildcard(span) | Pattern::Literal(_, span) => *span,
Pattern::Name(ident) => ident.span,
Pattern::Variant { span, .. }
| Pattern::Struct { span, .. }
| Pattern::Range { span, .. } => *span,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Literal {
Int { text: String, negative: bool },
Float { text: String, negative: bool },
Str(String),
Bool(bool),
}