Skip to main content

runar_compiler_rust/frontend/
ast.rs

1//! Rúnar AST types.
2//!
3//! These types mirror the TypeScript `runar-ast.ts` definitions. They represent
4//! the parsed contract structure before ANF lowering.
5
6// ---------------------------------------------------------------------------
7// Source locations
8// ---------------------------------------------------------------------------
9
10/// Source location in the original file.
11#[derive(Debug, Clone)]
12pub struct SourceLocation {
13    pub file: String,
14    pub line: usize,
15    pub column: usize,
16}
17
18// ---------------------------------------------------------------------------
19// Types
20// ---------------------------------------------------------------------------
21
22/// Primitive type names recognized by Rúnar.
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum PrimitiveTypeName {
25    Bigint,
26    Boolean,
27    ByteString,
28    PubKey,
29    Sig,
30    Sha256,
31    Ripemd160,
32    Addr,
33    SigHashPreimage,
34    RabinSig,
35    RabinPubKey,
36    Point,
37    Void,
38}
39
40impl PrimitiveTypeName {
41    /// Parse a string into a PrimitiveTypeName, if recognized.
42    pub fn from_str(s: &str) -> Option<PrimitiveTypeName> {
43        match s {
44            "bigint" => Some(PrimitiveTypeName::Bigint),
45            "boolean" => Some(PrimitiveTypeName::Boolean),
46            "ByteString" => Some(PrimitiveTypeName::ByteString),
47            "PubKey" => Some(PrimitiveTypeName::PubKey),
48            "Sig" => Some(PrimitiveTypeName::Sig),
49            "Sha256" => Some(PrimitiveTypeName::Sha256),
50            "Ripemd160" => Some(PrimitiveTypeName::Ripemd160),
51            "Addr" => Some(PrimitiveTypeName::Addr),
52            "SigHashPreimage" => Some(PrimitiveTypeName::SigHashPreimage),
53            "RabinSig" => Some(PrimitiveTypeName::RabinSig),
54            "RabinPubKey" => Some(PrimitiveTypeName::RabinPubKey),
55            "Point" => Some(PrimitiveTypeName::Point),
56            "void" => Some(PrimitiveTypeName::Void),
57            _ => None,
58        }
59    }
60
61    /// Convert back to string representation.
62    pub fn as_str(&self) -> &'static str {
63        match self {
64            PrimitiveTypeName::Bigint => "bigint",
65            PrimitiveTypeName::Boolean => "boolean",
66            PrimitiveTypeName::ByteString => "ByteString",
67            PrimitiveTypeName::PubKey => "PubKey",
68            PrimitiveTypeName::Sig => "Sig",
69            PrimitiveTypeName::Sha256 => "Sha256",
70            PrimitiveTypeName::Ripemd160 => "Ripemd160",
71            PrimitiveTypeName::Addr => "Addr",
72            PrimitiveTypeName::SigHashPreimage => "SigHashPreimage",
73            PrimitiveTypeName::RabinSig => "RabinSig",
74            PrimitiveTypeName::RabinPubKey => "RabinPubKey",
75            PrimitiveTypeName::Point => "Point",
76            PrimitiveTypeName::Void => "void",
77        }
78    }
79}
80
81/// A type node in the AST.
82#[derive(Debug, Clone)]
83pub enum TypeNode {
84    Primitive(PrimitiveTypeName),
85    FixedArray {
86        element: Box<TypeNode>,
87        length: usize,
88    },
89    Custom(String),
90}
91
92// ---------------------------------------------------------------------------
93// Top-level nodes
94// ---------------------------------------------------------------------------
95
96/// A complete Rúnar contract.
97#[derive(Debug, Clone)]
98pub struct ContractNode {
99    pub name: String,
100    pub parent_class: String, // "SmartContract" or "StatefulSmartContract"
101    pub properties: Vec<PropertyNode>,
102    pub constructor: MethodNode,
103    pub methods: Vec<MethodNode>,
104    pub source_file: String,
105}
106
107/// A contract property declaration.
108#[derive(Debug, Clone)]
109pub struct PropertyNode {
110    pub name: String,
111    pub prop_type: TypeNode,
112    pub readonly: bool,
113    pub initializer: Option<Expression>,
114    pub source_location: SourceLocation,
115}
116
117/// A method (constructor or named method).
118#[derive(Debug, Clone)]
119pub struct MethodNode {
120    pub name: String,
121    pub params: Vec<ParamNode>,
122    pub body: Vec<Statement>,
123    pub visibility: Visibility,
124    pub source_location: SourceLocation,
125}
126
127/// Method visibility.
128#[derive(Debug, Clone, PartialEq, Eq)]
129pub enum Visibility {
130    Public,
131    Private,
132}
133
134/// A method parameter.
135#[derive(Debug, Clone)]
136pub struct ParamNode {
137    pub name: String,
138    pub param_type: TypeNode,
139}
140
141// ---------------------------------------------------------------------------
142// Statements
143// ---------------------------------------------------------------------------
144
145/// Statement variants.
146#[derive(Debug, Clone)]
147pub enum Statement {
148    VariableDecl {
149        name: String,
150        var_type: Option<TypeNode>,
151        mutable: bool,
152        init: Expression,
153        source_location: SourceLocation,
154    },
155    Assignment {
156        target: Expression,
157        value: Expression,
158        source_location: SourceLocation,
159    },
160    IfStatement {
161        condition: Expression,
162        then_branch: Vec<Statement>,
163        else_branch: Option<Vec<Statement>>,
164        source_location: SourceLocation,
165    },
166    ForStatement {
167        init: Box<Statement>, // Always VariableDecl
168        condition: Expression,
169        update: Box<Statement>,
170        body: Vec<Statement>,
171        source_location: SourceLocation,
172    },
173    ReturnStatement {
174        value: Option<Expression>,
175        source_location: SourceLocation,
176    },
177    ExpressionStatement {
178        expression: Expression,
179        source_location: SourceLocation,
180    },
181}
182
183// ---------------------------------------------------------------------------
184// Expressions
185// ---------------------------------------------------------------------------
186
187/// Binary operator.
188#[derive(Debug, Clone, PartialEq, Eq)]
189pub enum BinaryOp {
190    Add,       // +
191    Sub,       // -
192    Mul,       // *
193    Div,       // /
194    Mod,       // %
195    StrictEq,  // ===
196    StrictNe,  // !==
197    Lt,        // <
198    Le,        // <=
199    Gt,        // >
200    Ge,        // >=
201    And,       // &&
202    Or,        // ||
203    BitAnd,    // &
204    BitOr,     // |
205    BitXor,    // ^
206    Shl,       // <<
207    Shr,       // >>
208}
209
210impl BinaryOp {
211    /// Convert to the string representation used in ANF IR.
212    pub fn as_str(&self) -> &'static str {
213        match self {
214            BinaryOp::Add => "+",
215            BinaryOp::Sub => "-",
216            BinaryOp::Mul => "*",
217            BinaryOp::Div => "/",
218            BinaryOp::Mod => "%",
219            BinaryOp::StrictEq => "===",
220            BinaryOp::StrictNe => "!==",
221            BinaryOp::Lt => "<",
222            BinaryOp::Le => "<=",
223            BinaryOp::Gt => ">",
224            BinaryOp::Ge => ">=",
225            BinaryOp::And => "&&",
226            BinaryOp::Or => "||",
227            BinaryOp::BitAnd => "&",
228            BinaryOp::BitOr => "|",
229            BinaryOp::BitXor => "^",
230            BinaryOp::Shl => "<<",
231            BinaryOp::Shr => ">>",
232        }
233    }
234}
235
236/// Unary operator.
237#[derive(Debug, Clone, PartialEq, Eq)]
238pub enum UnaryOp {
239    Not,    // !
240    Neg,    // -
241    BitNot, // ~
242}
243
244impl UnaryOp {
245    /// Convert to the string representation used in ANF IR.
246    pub fn as_str(&self) -> &'static str {
247        match self {
248            UnaryOp::Not => "!",
249            UnaryOp::Neg => "-",
250            UnaryOp::BitNot => "~",
251        }
252    }
253}
254
255/// Expression variants.
256#[derive(Debug, Clone)]
257pub enum Expression {
258    BinaryExpr {
259        op: BinaryOp,
260        left: Box<Expression>,
261        right: Box<Expression>,
262    },
263    UnaryExpr {
264        op: UnaryOp,
265        operand: Box<Expression>,
266    },
267    CallExpr {
268        callee: Box<Expression>,
269        args: Vec<Expression>,
270    },
271    MemberExpr {
272        object: Box<Expression>,
273        property: String,
274    },
275    Identifier {
276        name: String,
277    },
278    BigIntLiteral {
279        value: i64,
280    },
281    BoolLiteral {
282        value: bool,
283    },
284    ByteStringLiteral {
285        value: String, // hex-encoded
286    },
287    TernaryExpr {
288        condition: Box<Expression>,
289        consequent: Box<Expression>,
290        alternate: Box<Expression>,
291    },
292    PropertyAccess {
293        property: String, // this.x -> property = "x"
294    },
295    IndexAccess {
296        object: Box<Expression>,
297        index: Box<Expression>,
298    },
299    IncrementExpr {
300        operand: Box<Expression>,
301        prefix: bool,
302    },
303    DecrementExpr {
304        operand: Box<Expression>,
305        prefix: bool,
306    },
307}