extern crate alloc;
use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use crate::token::Span;
#[derive(Debug, Clone, PartialEq)]
pub struct Program {
pub uses: Vec<UseDecl>,
pub types: Vec<TypeDef>,
pub data_decls: Vec<DataDecl>,
pub functions: Vec<FunctionDef>,
pub traits: Vec<TraitDef>,
pub impls: Vec<ImplBlock>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct TraitDef {
pub name: String,
pub type_params: Vec<TypeParam>,
pub methods: Vec<TraitMethodSig>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct TraitMethodSig {
pub name: String,
pub params: Vec<Param>,
pub return_type: TypeExpr,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ImplBlock {
pub trait_name: String,
pub type_params: Vec<TypeParam>,
pub for_type: TypeExpr,
pub methods: Vec<FunctionDef>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct DataDecl {
pub name: String,
pub fields: Vec<DataFieldDecl>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct DataFieldDecl {
pub name: String,
pub type_expr: TypeExpr,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct UseDecl {
pub path: Vec<String>,
pub import: ImportItem,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ImportItem {
Name(String),
Wildcard,
}
#[derive(Debug, Clone, PartialEq)]
pub enum TypeDef {
Struct(StructDef),
Enum(EnumDef),
}
#[derive(Debug, Clone, PartialEq)]
pub struct StructDef {
pub name: String,
pub type_params: Vec<TypeParam>,
pub fields: Vec<FieldDecl>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct FieldDecl {
pub name: String,
pub type_expr: TypeExpr,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct EnumDef {
pub name: String,
pub type_params: Vec<TypeParam>,
pub variants: Vec<VariantDecl>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct VariantDecl {
pub name: String,
pub fields: Vec<TypeExpr>,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FunctionCategory {
Fn,
Yield,
Loop,
}
#[derive(Debug, Clone, PartialEq)]
pub struct FunctionDef {
pub category: FunctionCategory,
pub name: String,
pub type_params: Vec<TypeParam>,
pub params: Vec<Param>,
pub return_type: TypeExpr,
pub guard: Option<Box<Expr>>,
pub body: Block,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct TypeParam {
pub name: String,
pub bounds: Vec<String>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Param {
pub pattern: Pattern,
pub type_expr: Option<TypeExpr>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Block {
pub stmts: Vec<Stmt>,
pub tail_expr: Option<Box<Expr>>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Stmt {
Let(LetStmt),
For(ForStmt),
Break(Span),
DataFieldAssign {
data_name: String,
field: String,
value: Expr,
span: Span,
},
Expr(Expr),
}
#[derive(Debug, Clone, PartialEq)]
pub struct LetStmt {
pub pattern: Pattern,
pub type_expr: Option<TypeExpr>,
pub value: Expr,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ForStmt {
pub var: String,
pub iterable: Iterable,
pub body: Block,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Iterable {
Expr(Expr),
Range(Box<Expr>, Box<Expr>),
}
#[derive(Debug, Clone, PartialEq)]
pub enum Expr {
Literal { value: Literal, span: Span },
Ident { name: String, span: Span },
BinOp {
op: BinOp,
left: Box<Expr>,
right: Box<Expr>,
span: Span,
},
UnaryOp {
op: UnaryOp,
operand: Box<Expr>,
span: Span,
},
Call {
name: String,
args: Vec<Expr>,
span: Span,
},
Pipeline {
left: Box<Expr>,
func: String,
args: Vec<Expr>,
span: Span,
},
Yield { value: Box<Expr>, span: Span },
If {
condition: Box<Expr>,
then_block: Block,
else_block: Option<Block>,
span: Span,
},
Match {
scrutinee: Box<Expr>,
arms: Vec<MatchArm>,
span: Span,
},
Loop { body: Block, span: Span },
FieldAccess {
object: Box<Expr>,
field: String,
span: Span,
},
MethodCall {
receiver: Box<Expr>,
method: String,
args: Vec<Expr>,
span: Span,
},
TupleIndex {
object: Box<Expr>,
index: u64,
span: Span,
},
ArrayIndex {
object: Box<Expr>,
index: Box<Expr>,
span: Span,
},
StructInit {
name: String,
fields: Vec<FieldInit>,
span: Span,
},
EnumVariant {
enum_name: String,
variant: String,
args: Vec<Expr>,
span: Span,
},
ArrayLiteral { elements: Vec<Expr>, span: Span },
TupleLiteral { elements: Vec<Expr>, span: Span },
Cast {
expr: Box<Expr>,
target: TypeExpr,
span: Span,
},
Placeholder { span: Span },
Closure {
params: Vec<Param>,
return_type: Option<TypeExpr>,
body: Block,
span: Span,
},
ClosureRef {
name: String,
captures: Vec<String>,
recursive: bool,
span: Span,
},
}
impl Expr {
pub fn span(&self) -> Span {
match self {
Expr::Literal { span, .. }
| Expr::Ident { span, .. }
| Expr::BinOp { span, .. }
| Expr::UnaryOp { span, .. }
| Expr::Call { span, .. }
| Expr::Pipeline { span, .. }
| Expr::Yield { span, .. }
| Expr::If { span, .. }
| Expr::Match { span, .. }
| Expr::Loop { span, .. }
| Expr::FieldAccess { span, .. }
| Expr::MethodCall { span, .. }
| Expr::TupleIndex { span, .. }
| Expr::ArrayIndex { span, .. }
| Expr::StructInit { span, .. }
| Expr::EnumVariant { span, .. }
| Expr::ArrayLiteral { span, .. }
| Expr::TupleLiteral { span, .. }
| Expr::Cast { span, .. }
| Expr::Placeholder { span }
| Expr::Closure { span, .. }
| Expr::ClosureRef { span, .. } => *span,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Literal {
Int(i64),
Float(f64),
String(String),
Bool(bool),
Unit,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinOp {
Add,
Sub,
Mul,
Div,
Mod,
Eq,
NotEq,
Lt,
Gt,
LtEq,
GtEq,
And,
Or,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnaryOp {
Neg,
Not,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MatchArm {
pub pattern: Pattern,
pub expr: Expr,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct FieldInit {
pub name: String,
pub value: Expr,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub enum TypeExpr {
Prim(PrimType, Span),
Named(String, Vec<TypeExpr>, Span),
Tuple(Vec<TypeExpr>, Span),
Array(Box<TypeExpr>, i64, Span),
Option(Box<TypeExpr>, Span),
Unit(Span),
}
impl TypeExpr {
pub fn span(&self) -> Span {
match self {
TypeExpr::Prim(_, span)
| TypeExpr::Named(_, _, span)
| TypeExpr::Tuple(_, span)
| TypeExpr::Array(_, _, span)
| TypeExpr::Option(_, span)
| TypeExpr::Unit(span) => *span,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PrimType {
I64,
F64,
Bool,
KString,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Pattern {
Literal(Literal, Span),
Enum(String, String, Vec<Pattern>, Span),
Struct(String, Vec<FieldPattern>, Span),
Tuple(Vec<Pattern>, Span),
Wildcard(Span),
Variable(String, Span),
}
impl Pattern {
pub fn span(&self) -> Span {
match self {
Pattern::Literal(_, span)
| Pattern::Enum(_, _, _, span)
| Pattern::Struct(_, _, span)
| Pattern::Tuple(_, span)
| Pattern::Wildcard(span)
| Pattern::Variable(_, span) => *span,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct FieldPattern {
pub name: String,
pub pattern: Option<Pattern>,
pub span: Span,
}
pub fn merge_spans(start: Span, end: Span) -> Span {
Span {
start: start.start,
end: end.end,
line: start.line,
column: start.column,
}
}