//! Abstract syntax tree definitions for the doot language. use crate::lexer::Span; use std::collections::HashMap; /// Identifier type alias. pub type Ident = String; /// A parsed doot program. #[derive(Clone, Debug, PartialEq)] pub struct Program { pub statements: Vec>, } /// Wraps a node with source location information. #[derive(Clone, Debug, PartialEq)] pub struct Spanned { pub node: T, pub span: Span, } impl Spanned { /// Creates a new spanned node. pub fn new(node: T, span: Span) -> Self { Self { node, span } } } /// Top-level statement types. #[derive(Clone, Debug, PartialEq)] pub enum Statement { VarDecl(VarDecl), FnDecl(FnDecl), StructDecl(StructDecl), EnumDecl(EnumDecl), TypeAlias(TypeAlias), Import(Import), Dotfile(Dotfile), Package(Package), Secret(Secret), Hook(Hook), MacroDecl(MacroDecl), MacroCall(MacroCall), ForLoop(ForLoop), If(IfStatement), Match(MatchStatement), Expr(Expr), Return(Option), } /// Variable declaration. #[derive(Clone, Debug, PartialEq)] pub struct VarDecl { pub name: Ident, pub ty: Option, pub value: Expr, } /// Function declaration. #[derive(Clone, Debug, PartialEq)] pub struct FnDecl { pub name: Ident, pub is_async: bool, pub params: Vec, pub return_type: Option, pub body: Vec>, } /// Function parameter. #[derive(Clone, Debug, PartialEq)] pub struct FnParam { pub name: Ident, pub ty: TypeAnnotation, pub default: Option, } /// Struct type declaration. #[derive(Clone, Debug, PartialEq)] pub struct StructDecl { pub name: Ident, pub fields: Vec, pub methods: Vec, } /// Struct field definition. #[derive(Clone, Debug, PartialEq)] pub struct StructField { pub name: Ident, pub ty: TypeAnnotation, pub default: Option, } /// Enum type declaration. #[derive(Clone, Debug, PartialEq)] pub struct EnumDecl { pub name: Ident, pub variants: Vec, } /// Enum variant definition. #[derive(Clone, Debug, PartialEq)] pub struct EnumVariant { pub name: Ident, pub fields: Option>, } /// Type alias declaration. #[derive(Clone, Debug, PartialEq)] pub struct TypeAlias { pub name: Ident, pub ty: TypeAnnotation, } /// Module import statement. #[derive(Clone, Debug, PartialEq)] pub struct Import { pub path: String, pub alias: Option, } /// Deploy mode for dotfiles. #[derive(Clone, Copy, Debug, PartialEq, Default)] pub enum DeployMode { #[default] Copy, Link, } /// Permission rule - either a single mode or pattern-based. #[derive(Clone, Debug, PartialEq)] pub enum PermissionRule { Single(u32), Pattern { pattern: String, mode: u32 }, } /// Dotfile deployment declaration. #[derive(Clone, Debug, PartialEq)] pub struct Dotfile { pub source: Expr, pub target: Expr, pub when: Option, pub template: Option, pub permissions: Vec, pub owner: Option, pub deploy: DeployMode, pub link_patterns: Vec, pub copy_patterns: Vec, } /// Package installation declaration. #[derive(Clone, Debug, PartialEq)] pub struct Package { pub default: Option, pub brew: Option, pub apt: Option, pub pacman: Option, pub yay: Option, pub when: Option, } /// Package manager-specific specification. #[derive(Clone, Debug, PartialEq)] pub struct PackageSpec { pub name: Expr, pub cask: Option, pub tap: Option, } /// Encrypted secret file declaration. #[derive(Clone, Debug, PartialEq)] pub struct Secret { pub source: Expr, pub target: Expr, pub mode: Option, } /// Lifecycle hook declaration. #[derive(Clone, Debug, PartialEq)] pub struct Hook { pub stage: HookStage, pub run: Expr, pub when: Option, } /// Hook execution stage. #[derive(Clone, Debug, PartialEq)] pub enum HookStage { BeforeDeploy, AfterDeploy, BeforePackage, AfterPackage, } /// Macro definition. #[derive(Clone, Debug, PartialEq)] pub struct MacroDecl { pub name: Ident, pub params: Vec, pub body: Vec>, } /// Macro invocation. #[derive(Clone, Debug, PartialEq)] pub struct MacroCall { pub name: Ident, pub args: Vec, } /// For loop statement. #[derive(Clone, Debug, PartialEq)] pub struct ForLoop { pub var: Ident, pub iter: Expr, pub body: Vec>, } /// Conditional statement. #[derive(Clone, Debug, PartialEq)] pub struct IfStatement { pub condition: Expr, pub then_body: Vec>, pub else_body: Option>>, } /// Pattern matching statement. #[derive(Clone, Debug, PartialEq)] pub struct MatchStatement { pub expr: Expr, pub arms: Vec, } /// Single arm in a match statement. #[derive(Clone, Debug, PartialEq)] pub struct MatchArm { pub pattern: Pattern, pub body: Expr, } /// Match pattern types. #[derive(Clone, Debug, PartialEq)] pub enum Pattern { Literal(Literal), Ident(Ident), EnumVariant { ty: Ident, variant: Ident }, Wildcard, } /// Expression types. #[derive(Clone, Debug, PartialEq)] pub enum Expr { Literal(Literal), Ident(Ident), Path(Box, Box), Binary(Box, BinOp, Box), Unary(UnaryOp, Box), Call(Box, Vec), MethodCall(Box, Ident, Vec), Index(Box, Box), Field(Box, Ident), EnumVariant(Ident, Ident), StructInit(Ident, HashMap), List(Vec), If(Box, Box, Option>), Lambda(Vec, Box), Await(Box), Interpolated(Vec), HomePath(Box), } /// Part of an interpolated string. #[derive(Clone, Debug, PartialEq)] pub enum InterpolatedPart { Literal(String), Expr(Expr), } /// Literal value types. #[derive(Clone, Debug, PartialEq)] pub enum Literal { Int(i64), Float(f64), Str(String), Bool(bool), None, } /// Binary operators. #[derive(Clone, Debug, PartialEq)] pub enum BinOp { Add, Sub, Mul, Div, Mod, Eq, NotEq, Lt, Gt, LtEq, GtEq, And, Or, PathJoin, NullCoalesce, } /// Unary operators. #[derive(Clone, Debug, PartialEq)] pub enum UnaryOp { Neg, Not, } /// Type annotation in source code. #[derive(Clone, Debug, PartialEq)] pub enum TypeAnnotation { Simple(Ident), List(Box), Optional(Box), Function(Vec, Box), Union(Vec), Literal(Literal), }