Skip to main content

hiko_syntax/
ast.rs

1use crate::intern::Symbol;
2use crate::span::Span;
3
4// ── Expressions ──────────────────────────────────────────────────────
5
6#[derive(Debug, Clone, PartialEq)]
7pub struct Expr {
8    pub kind: ExprKind,
9    pub span: Span,
10}
11
12#[derive(Debug, Clone, PartialEq)]
13pub enum ExprKind {
14    IntLit(i64),
15    FloatLit(f64),
16    StringLit(String),
17    CharLit(char),
18    BoolLit(bool),
19    Unit,
20    Var(Symbol),
21    Constructor(Symbol),
22    Tuple(Vec<Expr>),
23    List(Vec<Expr>),
24    Cons(Box<Expr>, Box<Expr>),
25    BinOp(BinOp, Box<Expr>, Box<Expr>),
26    UnaryNeg(Box<Expr>),
27    Not(Box<Expr>),
28    App(Box<Expr>, Box<Expr>),
29    Fn(Pat, Box<Expr>),
30    If(Box<Expr>, Box<Expr>, Box<Expr>),
31    Let(Vec<Decl>, Box<Expr>),
32    Case(Box<Expr>, Vec<(Pat, Expr)>),
33    Ann(Box<Expr>, TypeExpr),
34    Paren(Box<Expr>),
35    /// `perform EffectName arg`
36    Perform(Symbol, Box<Expr>),
37    /// `handle body with return x => e | Effect x k => e`
38    Handle {
39        body: Box<Expr>,
40        return_var: Symbol,
41        return_body: Box<Expr>,
42        handlers: Vec<EffectHandler>,
43    },
44    /// `resume k value`
45    Resume(Box<Expr>, Box<Expr>),
46}
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49pub enum BinOp {
50    // Int arithmetic
51    AddInt,
52    SubInt,
53    MulInt,
54    DivInt,
55    ModInt,
56    // Float arithmetic
57    AddFloat,
58    SubFloat,
59    MulFloat,
60    DivFloat,
61    // String
62    ConcatStr,
63    // Int comparison
64    LtInt,
65    GtInt,
66    LeInt,
67    GeInt,
68    // Float comparison
69    LtFloat,
70    GtFloat,
71    LeFloat,
72    GeFloat,
73    // Equality (scalar only)
74    Eq,
75    Ne,
76    // Short-circuit boolean
77    Andalso,
78    Orelse,
79}
80
81// ── Declarations ─────────────────────────────────────────────────────
82
83#[derive(Debug, Clone, PartialEq)]
84pub struct Decl {
85    pub kind: DeclKind,
86    pub span: Span,
87}
88
89#[derive(Debug, Clone, PartialEq)]
90pub enum DeclKind {
91    /// `val p = e`
92    Val(Pat, Expr),
93    /// `val rec f = fn x => e`
94    ValRec(Symbol, Expr),
95    /// `fun f x1 x2 ... = e` (simple, possibly mutual via `and`)
96    Fun(Vec<FunBinding>),
97    /// `datatype ('a, 'b) T = C1 of t | C2 | ...`
98    Datatype(DatatypeDecl),
99    /// `type ('a, 'b) T = t`
100    TypeAlias(TypeAliasDecl),
101    /// `local d1 in d2 end`
102    Local(Vec<Decl>, Vec<Decl>),
103    /// `use "path/to/file.hml"`
104    Use(String),
105    /// `effect Yield of Int`
106    Effect(Symbol, Option<TypeExpr>),
107}
108
109#[derive(Debug, Clone, PartialEq)]
110pub struct FunBinding {
111    pub name: Symbol,
112    pub clauses: Vec<FunClause>,
113    pub span: Span,
114}
115
116#[derive(Debug, Clone, PartialEq)]
117pub struct FunClause {
118    pub pats: Vec<Pat>,
119    pub body: Expr,
120    pub span: Span,
121}
122
123#[derive(Debug, Clone, PartialEq)]
124pub struct DatatypeDecl {
125    pub tyvars: Vec<Symbol>,
126    pub name: Symbol,
127    pub constructors: Vec<ConDecl>,
128    pub span: Span,
129}
130
131#[derive(Debug, Clone, PartialEq)]
132pub struct ConDecl {
133    pub name: Symbol,
134    pub payload: Option<TypeExpr>,
135    pub span: Span,
136}
137
138#[derive(Debug, Clone, PartialEq)]
139pub struct TypeAliasDecl {
140    pub tyvars: Vec<Symbol>,
141    pub name: Symbol,
142    pub ty: TypeExpr,
143    pub span: Span,
144}
145
146#[derive(Debug, Clone, PartialEq)]
147pub struct EffectHandler {
148    pub effect_name: Symbol,
149    pub payload_var: Symbol,
150    pub cont_var: Symbol,
151    pub body: Expr,
152    pub span: Span,
153}
154
155// ── Patterns ─────────────────────────────────────────────────────────
156
157#[derive(Debug, Clone, PartialEq)]
158pub struct Pat {
159    pub kind: PatKind,
160    pub span: Span,
161}
162
163#[derive(Debug, Clone, PartialEq)]
164pub enum PatKind {
165    Wildcard,
166    Var(Symbol),
167    IntLit(i64),
168    FloatLit(f64),
169    StringLit(String),
170    CharLit(char),
171    BoolLit(bool),
172    Unit,
173    Tuple(Vec<Pat>),
174    Constructor(Symbol, Option<Box<Pat>>),
175    Cons(Box<Pat>, Box<Pat>),
176    List(Vec<Pat>),
177    Ann(Box<Pat>, TypeExpr),
178    As(Symbol, Box<Pat>),
179    Paren(Box<Pat>),
180}
181
182// ── Type expressions (surface syntax) ────────────────────────────────
183
184#[derive(Debug, Clone, PartialEq)]
185pub struct TypeExpr {
186    pub kind: TypeExprKind,
187    pub span: Span,
188}
189
190#[derive(Debug, Clone, PartialEq)]
191pub enum TypeExprKind {
192    /// A named type: `Int`, `Bool`, `option`, etc.
193    Named(Symbol),
194    /// A type variable: `'a`
195    Var(Symbol),
196    /// Type application: `'a list`, `('a, 'b) either`
197    App(Symbol, Vec<TypeExpr>),
198    /// Arrow: `a -> b`
199    Arrow(Box<TypeExpr>, Box<TypeExpr>),
200    /// Tuple: `a * b * c`
201    Tuple(Vec<TypeExpr>),
202    /// Parenthesized
203    Paren(Box<TypeExpr>),
204}
205
206// ── Program ──────────────────────────────────────────────────────────
207
208pub struct Program {
209    pub decls: Vec<Decl>,
210    pub interner: crate::intern::StringInterner,
211}
212
213impl std::fmt::Debug for Program {
214    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
215        f.debug_struct("Program")
216            .field("decls", &self.decls)
217            .finish()
218    }
219}