/// The AST for DreamStack. /// Homoiconic: every node is also representable as data (tagged vectors/maps). /// A complete DreamStack program is a list of top-level declarations. #[derive(Debug, Clone)] pub struct Program { pub declarations: Vec, } /// Top-level declarations. #[derive(Debug, Clone)] pub enum Declaration { /// `let name = expr` Let(LetDecl), /// `view name = expr` or `view name(params) = expr` View(ViewDecl), /// `effect name(params): ReturnType` Effect(EffectDecl), /// `on event_name -> body` OnHandler(OnHandler), /// `component Name(props) = body` Component(ComponentDecl), /// `route "/path" -> view_expr` Route(RouteDecl), /// `constrain element.prop = expr` Constrain(ConstrainDecl), } /// `let count = 0` or `let doubled = count * 2` #[derive(Debug, Clone)] pub struct LetDecl { pub name: String, pub value: Expr, pub span: Span, } /// `view counter = column [ ... ]` /// `view profile(id: UserId) = ...` #[derive(Debug, Clone)] pub struct ViewDecl { pub name: String, pub params: Vec, pub body: Expr, pub span: Span, } /// `effect fetchUser(id: UserId): Result` #[derive(Debug, Clone)] pub struct EffectDecl { pub name: String, pub params: Vec, pub return_type: TypeExpr, pub span: Span, } /// `on toggle_sidebar -> ...` #[derive(Debug, Clone)] pub struct OnHandler { pub event: String, pub param: Option, pub body: Expr, pub span: Span, } /// `component Card(title: String, children: View) = ...` #[derive(Debug, Clone)] pub struct ComponentDecl { pub name: String, pub props: Vec, pub body: Expr, pub span: Span, } /// `route "/users/:id" -> column [ text "User {id}" ]` #[derive(Debug, Clone)] pub struct RouteDecl { pub path: String, pub body: Expr, pub span: Span, } /// `constrain sidebar.width = clamp(200, parent.width * 0.2, 350)` #[derive(Debug, Clone)] pub struct ConstrainDecl { pub element: String, pub prop: String, pub expr: Expr, pub span: Span, } /// Function/view parameter. #[derive(Debug, Clone)] pub struct Param { pub name: String, pub type_annotation: Option, } /// Type expressions (simplified for Phase 0). #[derive(Debug, Clone)] pub enum TypeExpr { Named(String), Generic(String, Vec), } /// Expressions — the core of the language. #[derive(Debug, Clone)] pub enum Expr { /// Integer literal: `42` IntLit(i64), /// Float literal: `3.14` FloatLit(f64), /// String literal: `"hello"` (may contain `{interpolation}`) StringLit(StringLit), /// Boolean literal: `true` / `false` BoolLit(bool), /// Identifier: `count`, `sidebar.width` Ident(String), /// Dotted access: `user.name` DotAccess(Box, String), /// Binary operation: `a + b`, `count > 10` BinOp(Box, BinOp, Box), /// Unary operation: `-x`, `!flag` UnaryOp(UnaryOp, Box), /// Assignment: `count += 1`, `panel_x.target = 0` Assign(Box, AssignOp, Box), /// Function call: `clamp(200, 20vw, 350)` Call(String, Vec), /// Block: multiple expressions, last is the value Block(Vec), /// View element: `text "hello"`, `button "+" { click: ... }` Element(Element), /// Container: `column [ ... ]`, `row [ ... ]` Container(Container), /// When conditional: `when count > 10 -> ...` When(Box, Box), /// Match expression Match(Box, Vec), /// Pipe: `expr | operator` Pipe(Box, Box), /// `perform effectName(args)` Perform(String, Vec), /// `stream from source` StreamFrom(String), /// Lambda: `(x -> x * 2)` Lambda(Vec, Box), /// Record literal: `{ key: value, ... }` Record(Vec<(String, Expr)>), /// List literal: `[a, b, c]` List(Vec), /// `if cond then a else b` If(Box, Box, Box), /// Spring: `spring(target: 0, stiffness: 300, damping: 30)` Spring(Vec<(String, Expr)>), /// `for item in items -> body` with optional index `for item, i in items -> body` ForIn { item: String, index: Option, iter: Box, body: Box, }, /// Component instantiation: `` ComponentUse { name: String, props: Vec<(String, Expr)>, children: Vec, }, } /// String literal with interpolation segments. #[derive(Debug, Clone)] pub struct StringLit { pub segments: Vec, } #[derive(Debug, Clone)] pub enum StringSegment { Literal(String), Interpolation(Box), } /// Binary operators. #[derive(Debug, Clone, Copy, PartialEq)] pub enum BinOp { Add, Sub, Mul, Div, Mod, Eq, Neq, Lt, Gt, Lte, Gte, And, Or, } /// Unary operators. #[derive(Debug, Clone, Copy)] pub enum UnaryOp { Neg, Not, } /// Assignment operators. #[derive(Debug, Clone, Copy)] pub enum AssignOp { Set, AddAssign, SubAssign, } /// A UI element: `text label`, `button "+" { click: handler }` #[derive(Debug, Clone)] pub struct Element { pub tag: String, pub args: Vec, pub props: Vec<(String, Expr)>, pub modifiers: Vec, } /// A container: `column [ child1, child2 ]` #[derive(Debug, Clone)] pub struct Container { pub kind: ContainerKind, pub children: Vec, pub props: Vec<(String, Expr)>, } #[derive(Debug, Clone)] pub enum ContainerKind { Column, Row, Stack, List, Panel, Form, Scene, Custom(String), } /// Match arm: `Ok(u) -> column [ ... ]` #[derive(Debug, Clone)] pub struct MatchArm { pub pattern: Pattern, pub body: Expr, } /// Pattern matching. #[derive(Debug, Clone)] pub enum Pattern { Wildcard, Ident(String), Constructor(String, Vec), Literal(Expr), } /// Modifiers: `| animate fade-in 200ms` #[derive(Debug, Clone)] pub struct Modifier { pub name: String, pub args: Vec, } /// Source location tracking. #[derive(Debug, Clone, Copy, Default)] pub struct Span { pub start: usize, pub end: usize, pub line: usize, }