glyph_parser/
ast.rs

1//! Abstract Syntax Tree definitions for Glyph
2//!
3//! This module defines the AST nodes for the Glyph language, following
4//! the Python-like syntax from specification v0.3.
5
6use serde::{Deserialize, Serialize};
7use std::fmt;
8
9/// A complete Glyph module (file)
10#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11pub struct GlyphModule {
12    /// The @program decorator
13    pub program: ProgramDecorator,
14    /// Import statements
15    pub imports: Vec<Import>,
16    /// Top-level statements (mainly function definitions)
17    pub statements: Vec<Statement>,
18}
19
20/// The @program decorator that must appear at the start of every Glyph file
21#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
22pub struct ProgramDecorator {
23    /// Program name
24    pub name: String,
25    /// Program version
26    pub version: String,
27    /// Required capabilities
28    pub requires: Vec<String>,
29}
30
31/// Import statements
32#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
33pub enum Import {
34    /// `import module_name`
35    Module { name: String },
36    /// `from module_name import item1, item2`
37    FromImport { module: String, items: Vec<String> },
38}
39
40/// Statements in Glyph
41#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
42pub enum Statement {
43    /// Function definition
44    FunctionDef(Function),
45    /// Expression statement
46    Expression(Expression),
47    /// If statement
48    If(IfStatement),
49    /// Match statement
50    Match(MatchStatement),
51    /// Return statement
52    Return(Option<Expression>),
53    /// Let binding (immutable)
54    Let {
55        name: String,
56        value: Expression,
57        type_hint: Option<Type>,
58    },
59    /// Assignment (mutable)
60    Assignment { target: String, value: Expression },
61    /// While loop
62    While {
63        condition: Expression,
64        body: Vec<Statement>,
65    },
66    /// For loop
67    For {
68        variable: String,
69        iterable: Expression,
70        body: Vec<Statement>,
71    },
72    /// Break statement
73    Break,
74    /// Continue statement
75    Continue,
76}
77
78/// Function definition
79#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
80pub struct Function {
81    /// Function name
82    pub name: String,
83    /// Parameters
84    pub params: Vec<Parameter>,
85    /// Return type annotation
86    pub return_type: Option<Type>,
87    /// Function body
88    pub body: Vec<Statement>,
89    /// Whether this is an async function
90    pub is_async: bool,
91}
92
93/// Function parameter
94#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
95pub struct Parameter {
96    /// Parameter name
97    pub name: String,
98    /// Type annotation
99    pub type_hint: Option<Type>,
100    /// Default value
101    pub default: Option<Expression>,
102}
103
104/// If statement with optional elif and else clauses
105#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
106pub struct IfStatement {
107    /// Condition to test
108    pub condition: Expression,
109    /// Body executed if condition is true
110    pub then_body: Vec<Statement>,
111    /// Optional elif clauses
112    pub elif_clauses: Vec<ElifClause>,
113    /// Optional else body
114    pub else_body: Option<Vec<Statement>>,
115}
116
117/// Elif clause in an if statement
118#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
119pub struct ElifClause {
120    /// Condition to test
121    pub condition: Expression,
122    /// Body executed if condition is true
123    pub body: Vec<Statement>,
124}
125
126/// Match statement for pattern matching
127#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
128pub struct MatchStatement {
129    /// Expression to match against
130    pub subject: Expression,
131    /// Case clauses
132    pub cases: Vec<CaseClause>,
133}
134
135/// Case clause in a match statement
136#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
137pub struct CaseClause {
138    /// Pattern to match
139    pub pattern: Pattern,
140    /// Body executed if pattern matches
141    pub body: Vec<Statement>,
142}
143
144/// Patterns for match statements
145#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
146pub enum Pattern {
147    /// Literal pattern (int, float, string, bool)
148    Literal(Literal),
149    /// Variable binding pattern
150    Variable(String),
151    /// Constructor pattern like Ok(value) or Err(msg)
152    Constructor { name: String, args: Vec<Pattern> },
153    /// Wildcard pattern (_)
154    Wildcard,
155}
156
157/// Expressions in Glyph
158#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
159pub enum Expression {
160    /// Literal value
161    Literal(Literal),
162    /// Variable reference
163    Identifier(String),
164    /// Binary operation
165    BinaryOp {
166        left: Box<Expression>,
167        op: BinaryOperator,
168        right: Box<Expression>,
169    },
170    /// Unary operation
171    UnaryOp {
172        op: UnaryOperator,
173        operand: Box<Expression>,
174    },
175    /// Function call
176    Call {
177        func: Box<Expression>,
178        args: Vec<Expression>,
179        kwargs: Vec<(String, Expression)>,
180    },
181    /// Await expression
182    Await(Box<Expression>),
183    /// F-string
184    FString(Vec<FStringPart>),
185    /// List literal
186    List(Vec<Expression>),
187    /// Dict literal
188    Dict(Vec<(Expression, Expression)>),
189    /// Attribute access (e.g., voice.speak)
190    Attribute {
191        value: Box<Expression>,
192        attr: String,
193    },
194    /// If expression (ternary)
195    IfExpr {
196        test: Box<Expression>,
197        if_true: Box<Expression>,
198        if_false: Box<Expression>,
199    },
200}
201
202/// Parts of an f-string
203#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
204pub enum FStringPart {
205    /// Literal text
206    Text(String),
207    /// Interpolated expression
208    Expression(Expression),
209}
210
211/// Literal values
212#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
213pub enum Literal {
214    /// Integer literal
215    Int(i64),
216    /// Float literal
217    Float(f64),
218    /// String literal
219    String(String),
220    /// Boolean literal
221    Bool(bool),
222    /// None/unit literal
223    Unit,
224}
225
226/// Binary operators
227#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
228pub enum BinaryOperator {
229    // Arithmetic
230    Add,
231    Subtract,
232    Multiply,
233    Divide,
234    Modulo,
235    Power,
236    // Comparison
237    Equal,
238    NotEqual,
239    Less,
240    Greater,
241    LessEqual,
242    GreaterEqual,
243    // Logical
244    And,
245    Or,
246}
247
248/// Unary operators
249#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
250pub enum UnaryOperator {
251    /// Negation (-)
252    Negate,
253    /// Logical not
254    Not,
255}
256
257/// Type annotations
258#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
259pub enum Type {
260    /// Named type (int, float, str, bool, unit)
261    Named(String),
262    /// List type
263    List(Box<Type>),
264    /// Dict type
265    Dict { key: Box<Type>, value: Box<Type> },
266    /// Optional type
267    Optional(Box<Type>),
268    /// Promise type for async
269    Promise(Box<Type>),
270    /// Result type for errors
271    Result { ok: Box<Type>, err: Box<Type> },
272}
273
274/// Convenience type alias for the AST
275pub type GlyphAst = GlyphModule;
276
277impl fmt::Display for Type {
278    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
279        match self {
280            Type::Named(name) => write!(f, "{name}"),
281            Type::List(inner) => write!(f, "list[{inner}]"),
282            Type::Dict { key, value } => write!(f, "dict[{key}, {value}]"),
283            Type::Optional(inner) => write!(f, "optional[{inner}]"),
284            Type::Promise(inner) => write!(f, "promise[{inner}]"),
285            Type::Result { ok, err } => write!(f, "result[{ok}, {err}]"),
286        }
287    }
288}
289
290impl fmt::Display for BinaryOperator {
291    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
292        use BinaryOperator::*;
293        match self {
294            Add => write!(f, "+"),
295            Subtract => write!(f, "-"),
296            Multiply => write!(f, "*"),
297            Divide => write!(f, "/"),
298            Modulo => write!(f, "%"),
299            Power => write!(f, "**"),
300            Equal => write!(f, "=="),
301            NotEqual => write!(f, "!="),
302            Less => write!(f, "<"),
303            Greater => write!(f, ">"),
304            LessEqual => write!(f, "<="),
305            GreaterEqual => write!(f, ">="),
306            And => write!(f, "and"),
307            Or => write!(f, "or"),
308        }
309    }
310}