Skip to main content

ling/parser/
ast.rs

1// src/parser/ast.rs
2
3#[derive(Debug, Clone)]
4pub struct Program {
5    pub items: Vec<Item>,
6}
7
8#[derive(Debug, Clone)]
9pub enum Item {
10    Bind(String, Expr),
11    Fn(FnDef),
12    Mod(String, Vec<Item>),
13    TypeAlias(String, String), // type Name = RawType
14    /// `form Name { field, field, ... }` — record/struct definition.
15    /// Field types are parsed but ignored at runtime; only names (in order) survive.
16    Struct(String, Vec<String>),
17    /// `choose Name { Variant, Variant(a, b), ... }` — sum type / enum.
18    /// Each variant carries its name and payload arity (field names are ignored).
19    Enum(String, Vec<EnumVariant>),
20    /// `use "path/to/module"` or `use "path" as ns`
21    Use {
22        path: String,
23        alias: Option<String>,
24    },
25}
26
27#[derive(Debug, Clone)]
28pub struct EnumVariant {
29    pub name: String,
30    pub arity: usize,
31}
32
33#[derive(Debug, Clone)]
34pub struct FnDef {
35    pub name: String,
36    pub is_async: bool,
37    pub params: Vec<String>, // just names; types are parsed but ignored
38    pub body: Vec<Stmt>,
39}
40
41// ─── Expressions ─────────────────────────────────────────────────────────────
42
43#[derive(Debug, Clone)]
44pub enum Expr {
45    Str(String),
46    Number(f64),
47    Bool(bool),
48    Unit,
49    Ident(String),
50    /// `do { stmts }` or anonymous block `{ stmts }`
51    Do(Vec<Stmt>),
52    /// `if cond { then } (else if cond { elif })* (else { else_body })?`
53    If {
54        cond: Box<Expr>,
55        then: Vec<Stmt>,
56        elseifs: Vec<(Expr, Vec<Stmt>)>,
57        else_body: Option<Vec<Stmt>>,
58    },
59    /// `for name in iterable { body }`
60    For {
61        var: String,
62        iter: Box<Expr>,
63        body: Vec<Stmt>,
64    },
65    /// `while cond { body }` / `ขณะที่ cond { body }`
66    While {
67        cond: Box<Expr>,
68        body: Vec<Stmt>,
69    },
70    /// `match expr { arms }`
71    Match(Box<Expr>, Vec<MatchArm>),
72    /// Normal call: `expr(args)`
73    Call(Box<Expr>, Vec<Expr>),
74    /// Method call: `receiver.method(args)`
75    MethodCall {
76        receiver: Box<Expr>,
77        method: String,
78        args: Vec<Expr>,
79    },
80    /// Path like `Mod::fn` or just chained idents; resolved at runtime
81    Path(Vec<String>),
82    /// `lo..hi`
83    Range(Box<Expr>, Box<Expr>),
84    /// `&expr`
85    Ref(Box<Expr>),
86    /// `await expr`
87    Await(Box<Expr>),
88    /// Binary operation
89    BinOp(BinOp, Box<Expr>, Box<Expr>),
90    /// Array/Vec literal `[a, b, c]`
91    Array(Vec<Expr>),
92    /// `expr[idx]`
93    Index(Box<Expr>, Box<Expr>),
94    /// Closure `|| expr` or `|args| expr`
95    Closure(Vec<String>, Box<Expr>),
96}
97
98#[derive(Debug, Clone, PartialEq)]
99pub enum BinOp {
100    Add,
101    Sub,
102    Mul,
103    Div,
104    Rem,
105    Eq,
106    Ne,
107    Lt,
108    Gt,
109    Le,
110    Ge,
111    And,
112    Or,
113}
114
115// ─── Statements ──────────────────────────────────────────────────────────────
116
117#[derive(Debug, Clone)]
118pub enum Stmt {
119    Bind(String, Expr),
120    Expr(Expr),
121    Return(Expr),
122}
123
124// ─── Match arms ──────────────────────────────────────────────────────────────
125
126#[derive(Debug, Clone)]
127pub struct MatchArm {
128    pub pattern: Pattern,
129    pub body: Expr,
130}
131
132#[derive(Debug, Clone)]
133pub enum Pattern {
134    Wildcard,
135    Str(String),
136    Number(f64),
137    Bool(bool),
138    Ident(String),
139    /// Ok(inner), Bad(inner), 好(inner), 坏(inner)
140    Constructor(String, Option<Box<Pattern>>),
141    /// User enum variant: `Circle(r)`, `Pair(a, b)`, or nullary `Origin()`.
142    Variant(String, Vec<Pattern>),
143}