solscript_ast/
lib.rs

1//! SolScript Abstract Syntax Tree (Solidity-Style)
2//!
3//! This crate defines all AST node types for the SolScript language.
4
5mod span;
6mod types;
7
8pub use span::*;
9pub use types::*;
10
11use serde::{Deserialize, Serialize};
12use smol_str::SmolStr;
13
14/// A complete SolScript program (compilation unit)
15#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
16pub struct Program {
17    pub items: Vec<Item>,
18    pub span: Span,
19}
20
21/// Top-level items
22#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
23pub enum Item {
24    Import(ImportStmt),
25    Contract(ContractDef),
26    Interface(InterfaceDef),
27    Struct(StructDef),
28    Enum(EnumDef),
29    Event(EventDef),
30    Error(ErrorDef),
31    Function(FnDef),
32}
33
34// =============================================================================
35// Imports
36// =============================================================================
37
38#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
39pub struct ImportStmt {
40    pub items: Vec<ImportItem>,
41    pub source: SmolStr,
42    pub span: Span,
43}
44
45#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
46pub struct ImportItem {
47    pub name: Ident,
48    pub alias: Option<Ident>,
49    pub span: Span,
50}
51
52// =============================================================================
53// Visibility & Modifiers
54// =============================================================================
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
57pub enum Visibility {
58    Public,
59    Private,
60    Internal,
61    External,
62}
63
64#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
65pub enum StateMutability {
66    View,
67    Pure,
68    Payable,
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
72pub enum StorageLocation {
73    Memory,
74    Storage,
75    Calldata,
76}
77
78#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
79pub struct ModifierInvocation {
80    pub name: Ident,
81    pub args: Vec<Arg>,
82    pub span: Span,
83}
84
85// =============================================================================
86// Contract Definition
87// =============================================================================
88
89#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
90pub struct ContractDef {
91    pub attributes: Vec<Attribute>,
92    pub is_abstract: bool,
93    pub name: Ident,
94    pub bases: Vec<TypePath>,
95    pub members: Vec<ContractMember>,
96    pub span: Span,
97}
98
99#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
100pub enum ContractMember {
101    StateVar(StateVar),
102    Constructor(ConstructorDef),
103    Function(FnDef),
104    Modifier(ModifierDef),
105    Event(EventDef),
106    Error(ErrorDef),
107    Struct(StructDef),
108    Enum(EnumDef),
109}
110
111#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
112pub struct StateVar {
113    pub attributes: Vec<Attribute>,
114    pub ty: TypeExpr,
115    pub visibility: Option<Visibility>,
116    pub name: Ident,
117    pub initializer: Option<Expr>,
118    pub span: Span,
119}
120
121// =============================================================================
122// Interface Definition
123// =============================================================================
124
125#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
126pub struct InterfaceDef {
127    pub attributes: Vec<Attribute>,
128    pub name: Ident,
129    pub bases: Vec<TypePath>,
130    pub members: Vec<FnSig>,
131    pub span: Span,
132}
133
134#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
135pub struct FnSig {
136    pub name: Ident,
137    pub generic_params: Option<GenericParams>,
138    pub params: Vec<Param>,
139    pub visibility: Option<Visibility>,
140    pub state_mutability: Vec<StateMutability>,
141    pub modifiers: Vec<ModifierInvocation>,
142    pub return_params: Vec<ReturnParam>,
143    pub span: Span,
144}
145
146// =============================================================================
147// Struct Definition
148// =============================================================================
149
150#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
151pub struct StructDef {
152    pub attributes: Vec<Attribute>,
153    pub name: Ident,
154    pub generic_params: Option<GenericParams>,
155    pub fields: Vec<StructField>,
156    pub span: Span,
157}
158
159#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
160pub struct StructField {
161    pub ty: TypeExpr,
162    pub name: Ident,
163    pub span: Span,
164}
165
166// =============================================================================
167// Enum Definition
168// =============================================================================
169
170#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
171pub struct EnumDef {
172    pub attributes: Vec<Attribute>,
173    pub name: Ident,
174    pub variants: Vec<EnumVariant>,
175    pub span: Span,
176}
177
178#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
179pub struct EnumVariant {
180    pub name: Ident,
181    pub span: Span,
182}
183
184// =============================================================================
185// Event & Error Definitions
186// =============================================================================
187
188#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
189pub struct EventDef {
190    pub name: Ident,
191    pub params: Vec<EventParam>,
192    pub span: Span,
193}
194
195#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
196pub struct EventParam {
197    pub ty: TypeExpr,
198    pub indexed: bool,
199    pub name: Ident,
200    pub span: Span,
201}
202
203#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
204pub struct ErrorDef {
205    pub name: Ident,
206    pub params: Vec<ErrorParam>,
207    pub span: Span,
208}
209
210#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
211pub struct ErrorParam {
212    pub ty: TypeExpr,
213    pub name: Ident,
214    pub span: Span,
215}
216
217// =============================================================================
218// Constructor Definition
219// =============================================================================
220
221#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
222pub struct ConstructorDef {
223    pub params: Vec<Param>,
224    pub modifiers: Vec<ModifierInvocation>,
225    pub body: Block,
226    pub span: Span,
227}
228
229// =============================================================================
230// Modifier Definition
231// =============================================================================
232
233#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
234pub struct ModifierDef {
235    pub name: Ident,
236    pub params: Vec<Param>,
237    pub body: Block,
238    pub span: Span,
239}
240
241// =============================================================================
242// Function Definition
243// =============================================================================
244
245#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
246pub struct FnDef {
247    pub attributes: Vec<Attribute>,
248    pub name: Ident,
249    pub generic_params: Option<GenericParams>,
250    pub params: Vec<Param>,
251    pub visibility: Option<Visibility>,
252    pub state_mutability: Vec<StateMutability>,
253    pub modifiers: Vec<ModifierInvocation>,
254    pub return_params: Vec<ReturnParam>,
255    pub body: Option<Block>, // None for abstract functions
256    pub span: Span,
257}
258
259#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
260pub struct Param {
261    pub ty: TypeExpr,
262    pub storage_location: Option<StorageLocation>,
263    pub name: Ident,
264    pub span: Span,
265}
266
267#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
268pub struct ReturnParam {
269    pub ty: TypeExpr,
270    pub name: Option<Ident>,
271    pub span: Span,
272}
273
274// =============================================================================
275// Generics (for advanced features)
276// =============================================================================
277
278#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
279pub struct GenericParams {
280    pub params: Vec<GenericParam>,
281    pub span: Span,
282}
283
284#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
285pub struct GenericParam {
286    pub name: Ident,
287    pub bounds: Vec<TypeExpr>,
288    pub span: Span,
289}
290
291#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
292pub struct GenericArgs {
293    pub args: Vec<TypeExpr>,
294    pub span: Span,
295}
296
297// =============================================================================
298// Attributes (for metadata)
299// =============================================================================
300
301#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
302pub struct Attribute {
303    pub name: Ident,
304    pub args: Vec<AttributeArg>,
305    pub span: Span,
306}
307
308#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
309pub struct AttributeArg {
310    pub name: Option<Ident>,
311    pub value: AttributeValue,
312    pub span: Span,
313}
314
315#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
316pub enum AttributeValue {
317    Ident(Ident),
318    Literal(Literal),
319}
320
321// =============================================================================
322// Statements
323// =============================================================================
324
325#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
326pub struct Block {
327    pub stmts: Vec<Stmt>,
328    pub span: Span,
329}
330
331#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
332pub enum Stmt {
333    VarDecl(VarDeclStmt),
334    Return(ReturnStmt),
335    If(IfStmt),
336    While(WhileStmt),
337    For(ForStmt),
338    Emit(EmitStmt),
339    Require(RequireStmt),
340    Revert(RevertStmt),
341    Delete(DeleteStmt),
342    Selfdestruct(SelfdestructStmt),
343    Placeholder(Span), // _ in modifiers
344    Expr(ExprStmt),
345}
346
347#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
348pub struct VarDeclStmt {
349    pub ty: TypeExpr,
350    pub storage_location: Option<StorageLocation>,
351    pub name: Ident,
352    pub initializer: Option<Expr>,
353    pub span: Span,
354}
355
356#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
357pub struct ReturnStmt {
358    pub value: Option<Expr>,
359    pub span: Span,
360}
361
362#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
363pub struct IfStmt {
364    pub condition: Expr,
365    pub then_block: Block,
366    pub else_branch: Option<ElseBranch>,
367    pub span: Span,
368}
369
370#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
371pub enum ElseBranch {
372    ElseIf(Box<IfStmt>),
373    Else(Block),
374}
375
376#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
377pub struct WhileStmt {
378    pub condition: Expr,
379    pub body: Block,
380    pub span: Span,
381}
382
383#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
384pub struct ForStmt {
385    pub init: Option<ForInit>,
386    pub condition: Option<Expr>,
387    pub update: Option<Expr>,
388    pub body: Block,
389    pub span: Span,
390}
391
392#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
393pub enum ForInit {
394    VarDecl(VarDeclStmt),
395    Expr(Expr),
396}
397
398#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
399pub struct EmitStmt {
400    pub event: Ident,
401    pub args: Vec<Arg>,
402    pub span: Span,
403}
404
405#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
406pub struct RequireStmt {
407    pub condition: Expr,
408    pub message: Option<SmolStr>,
409    pub span: Span,
410}
411
412#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
413pub struct RevertStmt {
414    /// Either a string message or a custom error
415    pub kind: RevertKind,
416    pub span: Span,
417}
418
419#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
420pub enum RevertKind {
421    /// revert("message") or revert()
422    Message(Option<SmolStr>),
423    /// revert CustomError(args)
424    Error { name: Ident, args: Vec<Arg> },
425}
426
427#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
428pub struct DeleteStmt {
429    pub target: Expr,
430    pub span: Span,
431}
432
433#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
434pub struct SelfdestructStmt {
435    /// The recipient address to receive the rent
436    pub recipient: Expr,
437    pub span: Span,
438}
439
440#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
441pub struct ExprStmt {
442    pub expr: Expr,
443    pub span: Span,
444}
445
446// =============================================================================
447// Expressions
448// =============================================================================
449
450#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
451pub enum Expr {
452    Literal(Literal),
453    Ident(Ident),
454    Binary(Box<BinaryExpr>),
455    Unary(Box<UnaryExpr>),
456    Ternary(Box<TernaryExpr>),
457    Call(Box<CallExpr>),
458    MethodCall(Box<MethodCallExpr>),
459    FieldAccess(Box<FieldAccessExpr>),
460    Index(Box<IndexExpr>),
461    Array(ArrayExpr),
462    Tuple(TupleExpr),
463    New(Box<NewExpr>),
464    If(Box<IfExpr>),
465    Assign(Box<AssignExpr>),
466    Paren(Box<Expr>),
467}
468
469impl Expr {
470    pub fn span(&self) -> Span {
471        match self {
472            Expr::Literal(lit) => lit.span(),
473            Expr::Ident(id) => id.span,
474            Expr::Binary(b) => b.span,
475            Expr::Unary(u) => u.span,
476            Expr::Ternary(t) => t.span,
477            Expr::Call(c) => c.span,
478            Expr::MethodCall(m) => m.span,
479            Expr::FieldAccess(f) => f.span,
480            Expr::Index(i) => i.span,
481            Expr::Array(a) => a.span,
482            Expr::Tuple(t) => t.span,
483            Expr::New(n) => n.span,
484            Expr::If(i) => i.span,
485            Expr::Assign(a) => a.span,
486            Expr::Paren(e) => e.span(),
487        }
488    }
489}
490
491#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
492pub struct BinaryExpr {
493    pub left: Expr,
494    pub op: BinaryOp,
495    pub right: Expr,
496    pub span: Span,
497}
498
499#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
500pub enum BinaryOp {
501    // Arithmetic
502    Add,
503    Sub,
504    Mul,
505    Div,
506    Rem,
507    Exp, // **
508    // Comparison
509    Eq,
510    Ne,
511    Lt,
512    Le,
513    Gt,
514    Ge,
515    // Logical
516    And,
517    Or,
518    // Bitwise
519    BitAnd,
520    BitOr,
521    BitXor,
522    Shl,
523    Shr,
524}
525
526#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
527pub struct UnaryExpr {
528    pub op: UnaryOp,
529    pub expr: Expr,
530    pub span: Span,
531}
532
533#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
534pub enum UnaryOp {
535    Not,     // !
536    Neg,     // -
537    BitNot,  // ~
538    PreInc,  // ++x
539    PreDec,  // --x
540    PostInc, // x++
541    PostDec, // x--
542}
543
544#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
545pub struct TernaryExpr {
546    pub condition: Expr,
547    pub then_expr: Expr,
548    pub else_expr: Expr,
549    pub span: Span,
550}
551
552#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
553pub struct CallExpr {
554    pub callee: Expr,
555    pub args: Vec<Arg>,
556    pub span: Span,
557}
558
559#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
560pub struct Arg {
561    pub name: Option<Ident>,
562    pub value: Expr,
563    pub span: Span,
564}
565
566#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
567pub struct MethodCallExpr {
568    pub receiver: Expr,
569    pub method: Ident,
570    pub generic_args: Option<GenericArgs>,
571    pub args: Vec<Arg>,
572    pub span: Span,
573}
574
575#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
576pub struct FieldAccessExpr {
577    pub expr: Expr,
578    pub field: Ident,
579    pub span: Span,
580}
581
582#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
583pub struct IndexExpr {
584    pub expr: Expr,
585    pub index: Expr,
586    pub span: Span,
587}
588
589#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
590pub struct ArrayExpr {
591    pub elements: Vec<Expr>,
592    pub span: Span,
593}
594
595#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
596pub struct TupleExpr {
597    pub elements: Vec<Expr>,
598    pub span: Span,
599}
600
601#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
602pub struct NewExpr {
603    pub ty: TypePath,
604    pub args: Vec<Arg>,
605    pub span: Span,
606}
607
608#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
609pub struct IfExpr {
610    pub condition: Expr,
611    pub then_block: Block,
612    pub else_branch: Box<IfExprElse>,
613    pub span: Span,
614}
615
616#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
617pub enum IfExprElse {
618    ElseIf(IfExpr),
619    Else(Block),
620}
621
622#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
623pub struct AssignExpr {
624    pub target: Expr,
625    pub op: AssignOp,
626    pub value: Expr,
627    pub span: Span,
628}
629
630#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
631pub enum AssignOp {
632    Assign,
633    AddAssign,
634    SubAssign,
635    MulAssign,
636    DivAssign,
637    RemAssign,
638    BitAndAssign,
639    BitOrAssign,
640    BitXorAssign,
641}
642
643// =============================================================================
644// Literals
645// =============================================================================
646
647#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
648pub enum Literal {
649    Bool(bool, Span),
650    Int(u128, Span),
651    HexInt(SmolStr, Span),
652    String(SmolStr, Span),
653    HexString(SmolStr, Span),
654    Address(SmolStr, Span),
655}
656
657impl Literal {
658    pub fn span(&self) -> Span {
659        match self {
660            Literal::Bool(_, span) => *span,
661            Literal::Int(_, span) => *span,
662            Literal::HexInt(_, span) => *span,
663            Literal::String(_, span) => *span,
664            Literal::HexString(_, span) => *span,
665            Literal::Address(_, span) => *span,
666        }
667    }
668}
669
670// =============================================================================
671// Identifiers
672// =============================================================================
673
674#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
675pub struct Ident {
676    pub name: SmolStr,
677    pub span: Span,
678}
679
680impl Ident {
681    pub fn new(name: impl Into<SmolStr>, span: Span) -> Self {
682        Self {
683            name: name.into(),
684            span,
685        }
686    }
687}