Skip to main content

aver/
ast.rs

1#[derive(Debug, Clone, PartialEq)]
2pub enum Literal {
3    Int(i64),
4    Float(f64),
5    Str(String),
6    Bool(bool),
7}
8
9#[derive(Debug, Clone, PartialEq)]
10pub enum BinOp {
11    Add,
12    Sub,
13    Mul,
14    Div,
15    Eq,
16    Neq,
17    Lt,
18    Gt,
19    Lte,
20    Gte,
21}
22
23#[derive(Debug, Clone, PartialEq)]
24pub struct MatchArm {
25    pub pattern: Pattern,
26    pub body: Box<Expr>,
27}
28
29#[derive(Debug, Clone, PartialEq)]
30pub enum Pattern {
31    Wildcard,
32    Literal(Literal),
33    Ident(String),
34    /// Empty list pattern: `[]`
35    EmptyList,
36    /// Cons-like list pattern: `[head, ..tail]`
37    Cons(String, String),
38    /// Tuple pattern: `(a, b)` / `(_, x)` / nested tuples.
39    Tuple(Vec<Pattern>),
40    /// Constructor pattern: name + list of binding names.
41    /// Built-ins: Ok(x), Err(x), Some(x), None → vec!["x"] or vec![]
42    /// User-defined: Circle(r), Rect(w, h), Point → vec!["r"], vec!["w","h"], vec![]
43    Constructor(String, Vec<String>),
44}
45
46#[derive(Debug, Clone, PartialEq)]
47pub enum StrPart {
48    Literal(String),
49    Parsed(Box<Expr>),
50}
51
52#[derive(Debug, Clone, PartialEq)]
53pub enum Expr {
54    Literal(Literal),
55    Ident(String),
56    Attr(Box<Expr>, String),
57    FnCall(Box<Expr>, Vec<Expr>),
58    BinOp(BinOp, Box<Expr>, Box<Expr>),
59    Match {
60        subject: Box<Expr>,
61        arms: Vec<MatchArm>,
62        line: usize,
63    },
64    Pipe(Box<Expr>, Box<Expr>),
65    Constructor(String, Option<Box<Expr>>),
66    ErrorProp(Box<Expr>),
67    InterpolatedStr(Vec<StrPart>),
68    List(Vec<Expr>),
69    Tuple(Vec<Expr>),
70    /// Map literal: `{"a" => 1, "b" => 2}`
71    MapLiteral(Vec<(Expr, Expr)>),
72    /// Record creation: `User(name = "Alice", age = 30)`
73    RecordCreate {
74        type_name: String,
75        fields: Vec<(String, Expr)>,
76    },
77    /// Record update: `User.update(base, field = newVal, ...)`
78    RecordUpdate {
79        type_name: String,
80        base: Box<Expr>,
81        updates: Vec<(String, Expr)>,
82    },
83    /// Tail-position call to a function in the same SCC (self or mutual recursion).
84    /// Produced by the TCO transform pass before type-checking.
85    /// Boxed to keep Expr enum at its original size (48 bytes).
86    TailCall(Box<(String, Vec<Expr>)>),
87    /// Compiled variable lookup: `env[last][slot]` — O(1) instead of HashMap scan.
88    /// Produced by the resolver pass for locals inside function bodies.
89    Resolved(u16),
90}
91
92#[derive(Debug, Clone, PartialEq)]
93pub enum Stmt {
94    Binding(String, Option<String>, Expr),
95    Expr(Expr),
96}
97
98#[derive(Debug, Clone, PartialEq)]
99pub enum FnBody {
100    Expr(Expr),
101    Block(Vec<Stmt>),
102}
103
104/// Compile-time resolution metadata for a function body.
105/// Produced by `resolver::resolve_fn` — maps local variable names to slot indices
106/// so the interpreter can use `Vec<Rc<Value>>` instead of `HashMap` lookups.
107#[derive(Debug, Clone, PartialEq)]
108pub struct FnResolution {
109    /// Total number of local slots needed (params + bindings in body).
110    pub local_count: u16,
111    /// Map from local variable name → slot index in the local `Slots` frame.
112    pub local_slots: std::collections::HashMap<String, u16>,
113}
114
115#[derive(Debug, Clone, PartialEq)]
116pub struct FnDef {
117    pub name: String,
118    pub line: usize,
119    pub params: Vec<(String, String)>,
120    pub return_type: String,
121    pub effects: Vec<String>,
122    pub desc: Option<String>,
123    pub body: std::rc::Rc<FnBody>,
124    /// `None` for unresolved (REPL, module sub-interpreters).
125    pub resolution: Option<FnResolution>,
126}
127
128#[derive(Debug, Clone, PartialEq)]
129pub struct Module {
130    pub name: String,
131    pub depends: Vec<String>,
132    pub exposes: Vec<String>,
133    pub intent: String,
134}
135
136#[derive(Debug, Clone, PartialEq)]
137pub struct VerifyBlock {
138    pub fn_name: String,
139    pub cases: Vec<(Expr, Expr)>,
140}
141
142#[derive(Debug, Clone, PartialEq)]
143pub struct DecisionBlock {
144    pub name: String,
145    pub date: String,
146    pub reason: String,
147    pub chosen: String,
148    pub rejected: Vec<String>,
149    pub impacts: Vec<String>,
150    pub author: Option<String>,
151}
152
153/// A variant in a sum type definition.
154/// e.g. `Circle(Float)` → `TypeVariant { name: "Circle", fields: ["Float"] }`
155#[derive(Debug, Clone, PartialEq)]
156pub struct TypeVariant {
157    pub name: String,
158    pub fields: Vec<String>, // type annotations (e.g. "Float", "String")
159}
160
161/// A user-defined type definition.
162#[derive(Debug, Clone, PartialEq)]
163pub enum TypeDef {
164    /// `type Shape` with variants Circle(Float), Rect(Float, Float), Point
165    Sum {
166        name: String,
167        variants: Vec<TypeVariant>,
168        line: usize,
169    },
170    /// `record User` with fields name: String, age: Int
171    Product {
172        name: String,
173        fields: Vec<(String, String)>,
174        line: usize,
175    },
176}
177
178#[derive(Debug, Clone, PartialEq)]
179pub enum TopLevel {
180    Module(Module),
181    FnDef(FnDef),
182    Verify(VerifyBlock),
183    Decision(DecisionBlock),
184    Stmt(Stmt),
185    TypeDef(TypeDef),
186    /// `effects AppIO = [Console, Disk]` — named effect set (alias)
187    EffectSet {
188        name: String,
189        effects: Vec<String>,
190    },
191}