aether/
ast.rs

1// src/ast.rs
2//! Abstract Syntax Tree (AST) definitions for Aether
3//!
4//! This module defines the structure of Aether programs as a tree of nodes.
5
6/// Binary operators
7#[derive(Debug, Clone, PartialEq)]
8pub enum BinOp {
9    // Arithmetic
10    Add,      // +
11    Subtract, // -
12    Multiply, // *
13    Divide,   // /
14    Modulo,   // %
15
16    // Comparison
17    Equal,        // ==
18    NotEqual,     // !=
19    Less,         // <
20    LessEqual,    // <=
21    Greater,      // >
22    GreaterEqual, // >=
23
24    // Logical
25    And, // &&
26    Or,  // ||
27}
28
29/// Unary operators
30#[derive(Debug, Clone, PartialEq)]
31pub enum UnaryOp {
32    Minus, // -
33    Not,   // !
34}
35
36/// Expressions - things that evaluate to values
37#[derive(Debug, Clone, PartialEq)]
38pub enum Expr {
39    // Literals
40    Number(f64),
41    BigInteger(String), // 大整数字面量
42    String(String),
43    Boolean(bool),
44    Null,
45
46    // Identifier (variable reference)
47    Identifier(String),
48
49    // Binary operation: (left op right)
50    Binary {
51        left: Box<Expr>,
52        op: BinOp,
53        right: Box<Expr>,
54    },
55
56    // Unary operation: (op expr)
57    Unary {
58        op: UnaryOp,
59        expr: Box<Expr>,
60    },
61
62    // Function call: FUNC(arg1, arg2, ...)
63    Call {
64        func: Box<Expr>,
65        args: Vec<Expr>,
66    },
67
68    // Array literal: [1, 2, 3]
69    Array(Vec<Expr>),
70
71    // Dictionary literal: {key: value, ...}
72    Dict(Vec<(String, Expr)>),
73
74    // Array/Dict access: array[index] or dict[key]
75    Index {
76        object: Box<Expr>,
77        index: Box<Expr>,
78    },
79
80    // If expression (can return value)
81    If {
82        condition: Box<Expr>,
83        then_branch: Vec<Stmt>,
84        elif_branches: Vec<(Expr, Vec<Stmt>)>, // (condition, body) pairs
85        else_branch: Option<Vec<Stmt>>,
86    },
87
88    // Anonymous function
89    Lambda {
90        params: Vec<String>,
91        body: Vec<Stmt>,
92    },
93}
94
95/// Statements - things that perform actions
96#[derive(Debug, Clone, PartialEq)]
97pub enum Stmt {
98    // Variable assignment: Set NAME value
99    Set {
100        name: String,
101        value: Expr,
102    },
103
104    // Index assignment: Set OBJECT[INDEX] value (for arrays and dicts)
105    SetIndex {
106        object: Box<Expr>,
107        index: Box<Expr>,
108        value: Expr,
109    },
110
111    // Function definition: Func NAME (params) { body }
112    FuncDef {
113        name: String,
114        params: Vec<String>,
115        body: Vec<Stmt>,
116    },
117
118    // Generator definition: Generator NAME (params) { body }
119    GeneratorDef {
120        name: String,
121        params: Vec<String>,
122        body: Vec<Stmt>,
123    },
124
125    // Lazy variable: Lazy NAME (expr)
126    LazyDef {
127        name: String,
128        expr: Expr,
129    },
130
131    // Return statement: Return expr
132    Return(Expr),
133
134    // Yield statement (for generators): Yield expr
135    Yield(Expr),
136
137    // Break statement: Break (exit loop)
138    Break,
139
140    // Continue statement: Continue (skip to next iteration)
141    Continue,
142
143    // While loop: While (condition) { body }
144    While {
145        condition: Expr,
146        body: Vec<Stmt>,
147    },
148
149    // For loop: For VAR In ITERABLE { body }
150    For {
151        var: String,
152        iterable: Expr,
153        body: Vec<Stmt>,
154    },
155
156    // For loop with index: For INDEX, VAR In ITERABLE { body }
157    ForIndexed {
158        index_var: String,
159        value_var: String,
160        iterable: Expr,
161        body: Vec<Stmt>,
162    },
163
164    // Switch statement: Switch (expr) { Case val: body ... Default: body }
165    Switch {
166        expr: Expr,
167        cases: Vec<(Expr, Vec<Stmt>)>,
168        default: Option<Vec<Stmt>>,
169    },
170
171    // Import statement: Import NAME From PATH
172    Import {
173        names: Vec<String>,
174        path: String,
175        aliases: Vec<Option<String>>, // Optional aliases (as NAME)
176    },
177
178    // Export statement: Export NAME
179    Export(String),
180
181    // Throw statement: Throw message
182    Throw(Expr),
183
184    // Expression statement (expression as statement)
185    Expression(Expr),
186}
187
188/// A complete program is a list of statements
189pub type Program = Vec<Stmt>;
190
191impl Expr {
192    /// Helper to create a binary expression
193    pub fn binary(left: Expr, op: BinOp, right: Expr) -> Self {
194        Expr::Binary {
195            left: Box::new(left),
196            op,
197            right: Box::new(right),
198        }
199    }
200
201    /// Helper to create a unary expression
202    pub fn unary(op: UnaryOp, expr: Expr) -> Self {
203        Expr::Unary {
204            op,
205            expr: Box::new(expr),
206        }
207    }
208
209    /// Helper to create a function call
210    pub fn call(func: Expr, args: Vec<Expr>) -> Self {
211        Expr::Call {
212            func: Box::new(func),
213            args,
214        }
215    }
216
217    /// Helper to create an index expression
218    pub fn index(object: Expr, index: Expr) -> Self {
219        Expr::Index {
220            object: Box::new(object),
221            index: Box::new(index),
222        }
223    }
224}
225
226impl std::fmt::Display for BinOp {
227    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
228        match self {
229            BinOp::Add => write!(f, "+"),
230            BinOp::Subtract => write!(f, "-"),
231            BinOp::Multiply => write!(f, "*"),
232            BinOp::Divide => write!(f, "/"),
233            BinOp::Modulo => write!(f, "%"),
234            BinOp::Equal => write!(f, "=="),
235            BinOp::NotEqual => write!(f, "!="),
236            BinOp::Less => write!(f, "<"),
237            BinOp::LessEqual => write!(f, "<="),
238            BinOp::Greater => write!(f, ">"),
239            BinOp::GreaterEqual => write!(f, ">="),
240            BinOp::And => write!(f, "&&"),
241            BinOp::Or => write!(f, "||"),
242        }
243    }
244}
245
246impl std::fmt::Display for UnaryOp {
247    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
248        match self {
249            UnaryOp::Minus => write!(f, "-"),
250            UnaryOp::Not => write!(f, "!"),
251        }
252    }
253}
254
255#[cfg(test)]
256mod tests {
257    use super::*;
258
259    #[test]
260    fn test_expr_helpers() {
261        // Binary expression: 1 + 2
262        let expr = Expr::binary(Expr::Number(1.0), BinOp::Add, Expr::Number(2.0));
263        match expr {
264            Expr::Binary { left, op, right } => {
265                assert_eq!(*left, Expr::Number(1.0));
266                assert_eq!(op, BinOp::Add);
267                assert_eq!(*right, Expr::Number(2.0));
268            }
269            _ => panic!("Expected Binary expression"),
270        }
271
272        // Unary expression: -5
273        let expr = Expr::unary(UnaryOp::Minus, Expr::Number(5.0));
274        match expr {
275            Expr::Unary { op, expr } => {
276                assert_eq!(op, UnaryOp::Minus);
277                assert_eq!(*expr, Expr::Number(5.0));
278            }
279            _ => panic!("Expected Unary expression"),
280        }
281
282        // Function call: ADD(1, 2)
283        let expr = Expr::call(
284            Expr::Identifier("ADD".to_string()),
285            vec![Expr::Number(1.0), Expr::Number(2.0)],
286        );
287        match expr {
288            Expr::Call { func, args } => {
289                assert_eq!(*func, Expr::Identifier("ADD".to_string()));
290                assert_eq!(args.len(), 2);
291            }
292            _ => panic!("Expected Call expression"),
293        }
294    }
295
296    #[test]
297    fn test_binop_display() {
298        assert_eq!(format!("{}", BinOp::Add), "+");
299        assert_eq!(format!("{}", BinOp::Equal), "==");
300        assert_eq!(format!("{}", BinOp::And), "&&");
301    }
302
303    #[test]
304    fn test_unaryop_display() {
305        assert_eq!(format!("{}", UnaryOp::Minus), "-");
306        assert_eq!(format!("{}", UnaryOp::Not), "!");
307    }
308}