Skip to main content

cobble/
ast.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
4pub struct Program {
5    pub imports: Vec<Import>,
6    pub statements: Vec<Statement>,
7}
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10pub struct Import {
11    pub module: String,
12    pub items: Vec<String>, // Empty for "import module", non-empty for "from module import ..."
13}
14
15/// Type system for Cobble variables
16#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
17pub enum CobbleType {
18    Integer, // i32 - stored in scoreboard
19    Boolean, // bool - stored as 0/1 in scoreboard
20    String,  // String - only in function params/macros
21    List,    // List/Array - stored in storage
22    Map,     // Dictionary/Object - stored in storage
23    Unknown, // Type not yet inferred
24}
25
26impl CobbleType {
27    /// Get human-readable type name
28    pub fn name(&self) -> &str {
29        match self {
30            CobbleType::Integer => "integer",
31            CobbleType::Boolean => "boolean",
32            CobbleType::String => "string",
33            CobbleType::List => "list",
34            CobbleType::Map => "map",
35            CobbleType::Unknown => "unknown",
36        }
37    }
38}
39
40#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
41pub enum Statement {
42    Import(Import),
43    FunctionDef(FunctionDef),
44    Assignment(Assignment),
45    ConstAssignment(ConstAssignment), // const NAME = value
46    Expression(Expression),
47    If(IfStatement),
48    For(ForLoop),
49    While(WhileLoop),
50    Match(MatchStatement), // match/switch statement
51    Return(Option<Expression>),
52    Pass,
53    MinecraftCommand(String), // Commands starting with /
54    Global(Vec<String>),      // global var1, var2, ...
55    Execute(ExecuteBlock),    // as @s at @s: ... or asat @s: ...
56    SelectorDef(SelectorDef), // @Name = @a[...]
57    EntityDef(EntityDef),     // define @Name = @Selector ... create { ... }
58    CreateEntity(String),     // create @Name
59}
60
61#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
62pub struct EntityDef {
63    pub name: String,
64    pub selector: String,
65    pub nbt: Expression,
66}
67
68#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
69pub struct FunctionDef {
70    pub name: String,
71    pub params: Vec<Parameter>,
72    pub body: Vec<Statement>,
73    pub decorators: Vec<String>,
74}
75
76#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
77pub struct Parameter {
78    pub name: String,
79    pub default: Option<Expression>,
80}
81
82#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
83pub struct Assignment {
84    pub target: String,
85    pub value: Expression,
86}
87
88#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
89pub struct ConstAssignment {
90    pub target: String,
91    pub value: Expression,
92}
93
94#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
95pub struct IfStatement {
96    pub condition: Expression,
97    pub then_branch: Vec<Statement>,
98    pub elif_branches: Vec<(Expression, Vec<Statement>)>,
99    pub else_branch: Option<Vec<Statement>>,
100}
101
102#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
103pub struct ForLoop {
104    pub target: String,
105    pub iter: Expression,
106    pub step: Option<Expression>, // Optional step value (for range with step)
107    pub body: Vec<Statement>,
108}
109
110#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
111pub struct WhileLoop {
112    pub condition: Expression,
113    pub body: Vec<Statement>,
114}
115
116#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
117pub struct MatchStatement {
118    pub value: Expression,
119    pub cases: Vec<MatchCase>,
120}
121
122#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
123pub struct MatchCase {
124    pub pattern: MatchPattern,
125    pub body: Vec<Statement>,
126}
127
128#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
129pub enum MatchPattern {
130    Literal(i32),    // case 5:
131    Range(i32, i32), // case 1 to 10:
132    Wildcard,        // case _:
133}
134
135#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
136pub struct ExecuteBlock {
137    pub modifiers: Vec<ExecuteModifier>, // as @a, at @s, if block ..., etc.
138    pub body: Vec<Statement>,
139}
140
141#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
142pub enum ExecuteModifier {
143    As(String),         // as @a
144    At(String),         // at @s
145    If(Expression),     // if x > 0 (Python-style expression)
146    IfRaw(String),      // if block ~ ~ ~ stone (raw Minecraft syntax)
147    Unless(Expression), // unless x > 0 (Python-style expression)
148    UnlessRaw(String),  // unless entity @a[tag=done] (raw Minecraft syntax)
149    Positioned(String), // positioned ~ ~1 ~
150    Rotated(String),    // rotated ~ ~
151    In(String),         // in minecraft:the_nether
152    Anchored(String),   // anchored eyes
153    Align(String),      // align xyz
154    Store(String),      // store result score ...
155}
156
157#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
158pub struct SelectorDef {
159    pub name: String,     // e.g., "Player"
160    pub selector: String, // e.g., "@a[type=player,gamemode=survival]"
161}
162
163#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
164pub enum Expression {
165    // Literals
166    Number(f64),
167    String(String),
168    Boolean(bool),
169    None,
170    Array(Vec<Expression>),
171    Map(Vec<(String, Expression)>),
172
173    // Identifiers and attributes
174    Identifier(String),
175    Attribute(Box<Expression>, String), // e.g., stdlib.event.TICK
176
177    // Operations
178    Binary(Box<Expression>, BinaryOp, Box<Expression>),
179    Unary(UnaryOp, Box<Expression>),
180
181    // Function calls
182    Call(Box<Expression>, Vec<Expression>),
183
184    // Subscript
185    Subscript(Box<Expression>, Box<Expression>),
186}
187
188#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
189pub enum BinaryOp {
190    // Arithmetic
191    Add,
192    Sub,
193    Mul,
194    Div,
195    Mod,
196    Pow,
197
198    // Comparison
199    Eq,
200    NotEq,
201    Lt,
202    LtEq,
203    Gt,
204    GtEq,
205
206    // Logical
207    And,
208    Or,
209}
210
211#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
212pub enum UnaryOp {
213    Not,
214    Neg,
215    Pos,
216}