1use harn_lexer::{Span, StringSegment};
2
3#[derive(Debug, Clone, PartialEq)]
5pub struct Spanned<T> {
6 pub node: T,
7 pub span: Span,
8}
9
10impl<T> Spanned<T> {
11 pub fn new(node: T, span: Span) -> Self {
12 Self { node, span }
13 }
14
15 pub fn dummy(node: T) -> Self {
16 Self {
17 node,
18 span: Span::dummy(),
19 }
20 }
21}
22
23pub type SNode = Spanned<Node>;
25
26pub fn spanned(node: Node, span: Span) -> SNode {
28 SNode::new(node, span)
29}
30
31#[derive(Debug, Clone, PartialEq)]
33pub enum Node {
34 Pipeline {
36 name: String,
37 params: Vec<String>,
38 body: Vec<SNode>,
39 extends: Option<String>,
40 },
41 LetBinding {
42 pattern: BindingPattern,
43 type_ann: Option<TypeExpr>,
44 value: Box<SNode>,
45 },
46 VarBinding {
47 pattern: BindingPattern,
48 type_ann: Option<TypeExpr>,
49 value: Box<SNode>,
50 },
51 OverrideDecl {
52 name: String,
53 params: Vec<String>,
54 body: Vec<SNode>,
55 },
56 ImportDecl {
57 path: String,
58 },
59 SelectiveImport {
61 names: Vec<String>,
62 path: String,
63 },
64 EnumDecl {
65 name: String,
66 variants: Vec<EnumVariant>,
67 },
68 StructDecl {
69 name: String,
70 fields: Vec<StructField>,
71 },
72 InterfaceDecl {
73 name: String,
74 methods: Vec<InterfaceMethod>,
75 },
76
77 IfElse {
79 condition: Box<SNode>,
80 then_body: Vec<SNode>,
81 else_body: Option<Vec<SNode>>,
82 },
83 ForIn {
84 pattern: BindingPattern,
85 iterable: Box<SNode>,
86 body: Vec<SNode>,
87 },
88 MatchExpr {
89 value: Box<SNode>,
90 arms: Vec<MatchArm>,
91 },
92 WhileLoop {
93 condition: Box<SNode>,
94 body: Vec<SNode>,
95 },
96 Retry {
97 count: Box<SNode>,
98 body: Vec<SNode>,
99 },
100 ReturnStmt {
101 value: Option<Box<SNode>>,
102 },
103 TryCatch {
104 body: Vec<SNode>,
105 error_var: Option<String>,
106 error_type: Option<TypeExpr>,
107 catch_body: Vec<SNode>,
108 },
109 FnDecl {
110 name: String,
111 params: Vec<TypedParam>,
112 return_type: Option<TypeExpr>,
113 body: Vec<SNode>,
114 is_pub: bool,
115 },
116 TypeDecl {
117 name: String,
118 type_expr: TypeExpr,
119 },
120 SpawnExpr {
121 body: Vec<SNode>,
122 },
123 DurationLiteral(u64),
125 RangeExpr {
127 start: Box<SNode>,
128 end: Box<SNode>,
129 inclusive: bool,
130 },
131 GuardStmt {
133 condition: Box<SNode>,
134 else_body: Vec<SNode>,
135 },
136 AskExpr {
138 fields: Vec<DictEntry>,
139 },
140 DeadlineBlock {
142 duration: Box<SNode>,
143 body: Vec<SNode>,
144 },
145 YieldExpr {
147 value: Option<Box<SNode>>,
148 },
149 MutexBlock {
151 body: Vec<SNode>,
152 },
153 BreakStmt,
155 ContinueStmt,
157
158 Parallel {
160 count: Box<SNode>,
161 variable: Option<String>,
162 body: Vec<SNode>,
163 },
164 ParallelMap {
165 list: Box<SNode>,
166 variable: String,
167 body: Vec<SNode>,
168 },
169
170 FunctionCall {
172 name: String,
173 args: Vec<SNode>,
174 },
175 MethodCall {
176 object: Box<SNode>,
177 method: String,
178 args: Vec<SNode>,
179 },
180 OptionalMethodCall {
182 object: Box<SNode>,
183 method: String,
184 args: Vec<SNode>,
185 },
186 PropertyAccess {
187 object: Box<SNode>,
188 property: String,
189 },
190 OptionalPropertyAccess {
192 object: Box<SNode>,
193 property: String,
194 },
195 SubscriptAccess {
196 object: Box<SNode>,
197 index: Box<SNode>,
198 },
199 SliceAccess {
200 object: Box<SNode>,
201 start: Option<Box<SNode>>,
202 end: Option<Box<SNode>>,
203 },
204 BinaryOp {
205 op: String,
206 left: Box<SNode>,
207 right: Box<SNode>,
208 },
209 UnaryOp {
210 op: String,
211 operand: Box<SNode>,
212 },
213 Ternary {
214 condition: Box<SNode>,
215 true_expr: Box<SNode>,
216 false_expr: Box<SNode>,
217 },
218 Assignment {
219 target: Box<SNode>,
220 value: Box<SNode>,
221 op: Option<String>,
223 },
224 ThrowStmt {
225 value: Box<SNode>,
226 },
227
228 EnumConstruct {
230 enum_name: String,
231 variant: String,
232 args: Vec<SNode>,
233 },
234 StructConstruct {
236 struct_name: String,
237 fields: Vec<DictEntry>,
238 },
239
240 InterpolatedString(Vec<StringSegment>),
242 StringLiteral(String),
243 IntLiteral(i64),
244 FloatLiteral(f64),
245 BoolLiteral(bool),
246 NilLiteral,
247 Identifier(String),
248 ListLiteral(Vec<SNode>),
249 DictLiteral(Vec<DictEntry>),
250 Spread(Box<SNode>),
252
253 Block(Vec<SNode>),
255 Closure {
256 params: Vec<TypedParam>,
257 body: Vec<SNode>,
258 },
259}
260
261#[derive(Debug, Clone, PartialEq)]
262pub struct MatchArm {
263 pub pattern: SNode,
264 pub body: Vec<SNode>,
265}
266
267#[derive(Debug, Clone, PartialEq)]
268pub struct DictEntry {
269 pub key: SNode,
270 pub value: SNode,
271}
272
273#[derive(Debug, Clone, PartialEq)]
275pub struct EnumVariant {
276 pub name: String,
277 pub fields: Vec<TypedParam>,
278}
279
280#[derive(Debug, Clone, PartialEq)]
282pub struct StructField {
283 pub name: String,
284 pub type_expr: Option<TypeExpr>,
285 pub optional: bool,
286}
287
288#[derive(Debug, Clone, PartialEq)]
290pub struct InterfaceMethod {
291 pub name: String,
292 pub params: Vec<TypedParam>,
293 pub return_type: Option<TypeExpr>,
294}
295
296#[derive(Debug, Clone, PartialEq)]
298pub enum TypeExpr {
299 Named(String),
302 Union(Vec<TypeExpr>),
304 Shape(Vec<ShapeField>),
306 List(Box<TypeExpr>),
308 DictType(Box<TypeExpr>, Box<TypeExpr>),
310}
311
312#[derive(Debug, Clone, PartialEq)]
314pub struct ShapeField {
315 pub name: String,
316 pub type_expr: TypeExpr,
317 pub optional: bool,
318}
319
320#[derive(Debug, Clone, PartialEq)]
322pub enum BindingPattern {
323 Identifier(String),
325 Dict(Vec<DictPatternField>),
327 List(Vec<ListPatternElement>),
329}
330
331#[derive(Debug, Clone, PartialEq)]
333pub struct DictPatternField {
334 pub key: String,
336 pub alias: Option<String>,
338 pub is_rest: bool,
340}
341
342#[derive(Debug, Clone, PartialEq)]
344pub struct ListPatternElement {
345 pub name: String,
347 pub is_rest: bool,
349}
350
351#[derive(Debug, Clone, PartialEq)]
353pub struct TypedParam {
354 pub name: String,
355 pub type_expr: Option<TypeExpr>,
356}
357
358impl TypedParam {
359 pub fn untyped(name: impl Into<String>) -> Self {
361 Self {
362 name: name.into(),
363 type_expr: None,
364 }
365 }
366
367 pub fn typed(name: impl Into<String>, type_expr: TypeExpr) -> Self {
369 Self {
370 name: name.into(),
371 type_expr: Some(type_expr),
372 }
373 }
374
375 pub fn names(params: &[TypedParam]) -> Vec<String> {
377 params.iter().map(|p| p.name.clone()).collect()
378 }
379}