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 is_pub: bool,
41 },
42 LetBinding {
43 pattern: BindingPattern,
44 type_ann: Option<TypeExpr>,
45 value: Box<SNode>,
46 },
47 VarBinding {
48 pattern: BindingPattern,
49 type_ann: Option<TypeExpr>,
50 value: Box<SNode>,
51 },
52 OverrideDecl {
53 name: String,
54 params: Vec<String>,
55 body: Vec<SNode>,
56 },
57 ImportDecl {
58 path: String,
59 },
60 SelectiveImport {
62 names: Vec<String>,
63 path: String,
64 },
65 EnumDecl {
66 name: String,
67 variants: Vec<EnumVariant>,
68 is_pub: bool,
69 },
70 StructDecl {
71 name: String,
72 fields: Vec<StructField>,
73 is_pub: bool,
74 },
75 InterfaceDecl {
76 name: String,
77 type_params: Vec<TypeParam>,
78 methods: Vec<InterfaceMethod>,
79 },
80 ImplBlock {
82 type_name: String,
83 methods: Vec<SNode>,
84 },
85
86 IfElse {
88 condition: Box<SNode>,
89 then_body: Vec<SNode>,
90 else_body: Option<Vec<SNode>>,
91 },
92 ForIn {
93 pattern: BindingPattern,
94 iterable: Box<SNode>,
95 body: Vec<SNode>,
96 },
97 MatchExpr {
98 value: Box<SNode>,
99 arms: Vec<MatchArm>,
100 },
101 WhileLoop {
102 condition: Box<SNode>,
103 body: Vec<SNode>,
104 },
105 Retry {
106 count: Box<SNode>,
107 body: Vec<SNode>,
108 },
109 ReturnStmt {
110 value: Option<Box<SNode>>,
111 },
112 TryCatch {
113 body: Vec<SNode>,
114 error_var: Option<String>,
115 error_type: Option<TypeExpr>,
116 catch_body: Vec<SNode>,
117 finally_body: Option<Vec<SNode>>,
118 },
119 TryExpr {
121 body: Vec<SNode>,
122 },
123 FnDecl {
124 name: String,
125 type_params: Vec<TypeParam>,
126 params: Vec<TypedParam>,
127 return_type: Option<TypeExpr>,
128 where_clauses: Vec<WhereClause>,
129 body: Vec<SNode>,
130 is_pub: bool,
131 },
132 ToolDecl {
133 name: String,
134 description: Option<String>,
135 params: Vec<TypedParam>,
136 return_type: Option<TypeExpr>,
137 body: Vec<SNode>,
138 is_pub: bool,
139 },
140 TypeDecl {
141 name: String,
142 type_expr: TypeExpr,
143 },
144 SpawnExpr {
145 body: Vec<SNode>,
146 },
147 DurationLiteral(u64),
149 RangeExpr {
151 start: Box<SNode>,
152 end: Box<SNode>,
153 inclusive: bool,
154 },
155 GuardStmt {
157 condition: Box<SNode>,
158 else_body: Vec<SNode>,
159 },
160 RequireStmt {
161 condition: Box<SNode>,
162 message: Option<Box<SNode>>,
163 },
164 DeferStmt {
166 body: Vec<SNode>,
167 },
168 DeadlineBlock {
170 duration: Box<SNode>,
171 body: Vec<SNode>,
172 },
173 YieldExpr {
175 value: Option<Box<SNode>>,
176 },
177 MutexBlock {
179 body: Vec<SNode>,
180 },
181 BreakStmt,
183 ContinueStmt,
185
186 Parallel {
188 mode: ParallelMode,
189 expr: Box<SNode>,
191 variable: Option<String>,
192 body: Vec<SNode>,
193 },
194
195 SelectExpr {
196 cases: Vec<SelectCase>,
197 timeout: Option<(Box<SNode>, Vec<SNode>)>,
198 default_body: Option<Vec<SNode>>,
199 },
200
201 FunctionCall {
203 name: String,
204 args: Vec<SNode>,
205 },
206 MethodCall {
207 object: Box<SNode>,
208 method: String,
209 args: Vec<SNode>,
210 },
211 OptionalMethodCall {
213 object: Box<SNode>,
214 method: String,
215 args: Vec<SNode>,
216 },
217 PropertyAccess {
218 object: Box<SNode>,
219 property: String,
220 },
221 OptionalPropertyAccess {
223 object: Box<SNode>,
224 property: String,
225 },
226 SubscriptAccess {
227 object: Box<SNode>,
228 index: Box<SNode>,
229 },
230 SliceAccess {
231 object: Box<SNode>,
232 start: Option<Box<SNode>>,
233 end: Option<Box<SNode>>,
234 },
235 BinaryOp {
236 op: String,
237 left: Box<SNode>,
238 right: Box<SNode>,
239 },
240 UnaryOp {
241 op: String,
242 operand: Box<SNode>,
243 },
244 Ternary {
245 condition: Box<SNode>,
246 true_expr: Box<SNode>,
247 false_expr: Box<SNode>,
248 },
249 Assignment {
250 target: Box<SNode>,
251 value: Box<SNode>,
252 op: Option<String>,
254 },
255 ThrowStmt {
256 value: Box<SNode>,
257 },
258
259 EnumConstruct {
261 enum_name: String,
262 variant: String,
263 args: Vec<SNode>,
264 },
265 StructConstruct {
267 struct_name: String,
268 fields: Vec<DictEntry>,
269 },
270
271 InterpolatedString(Vec<StringSegment>),
273 StringLiteral(String),
274 RawStringLiteral(String),
276 IntLiteral(i64),
277 FloatLiteral(f64),
278 BoolLiteral(bool),
279 NilLiteral,
280 Identifier(String),
281 ListLiteral(Vec<SNode>),
282 DictLiteral(Vec<DictEntry>),
283 Spread(Box<SNode>),
285 TryOperator {
287 operand: Box<SNode>,
288 },
289
290 Block(Vec<SNode>),
292 Closure {
293 params: Vec<TypedParam>,
294 body: Vec<SNode>,
295 fn_syntax: bool,
298 },
299}
300
301#[derive(Debug, Clone, Copy, PartialEq)]
303pub enum ParallelMode {
304 Count,
306 Each,
308 Settle,
310}
311
312#[derive(Debug, Clone, PartialEq)]
313pub struct MatchArm {
314 pub pattern: SNode,
315 pub guard: Option<Box<SNode>>,
317 pub body: Vec<SNode>,
318}
319
320#[derive(Debug, Clone, PartialEq)]
321pub struct SelectCase {
322 pub variable: String,
323 pub channel: Box<SNode>,
324 pub body: Vec<SNode>,
325}
326
327#[derive(Debug, Clone, PartialEq)]
328pub struct DictEntry {
329 pub key: SNode,
330 pub value: SNode,
331}
332
333#[derive(Debug, Clone, PartialEq)]
335pub struct EnumVariant {
336 pub name: String,
337 pub fields: Vec<TypedParam>,
338}
339
340#[derive(Debug, Clone, PartialEq)]
342pub struct StructField {
343 pub name: String,
344 pub type_expr: Option<TypeExpr>,
345 pub optional: bool,
346}
347
348#[derive(Debug, Clone, PartialEq)]
350pub struct InterfaceMethod {
351 pub name: String,
352 pub type_params: Vec<TypeParam>,
353 pub params: Vec<TypedParam>,
354 pub return_type: Option<TypeExpr>,
355}
356
357#[derive(Debug, Clone, PartialEq)]
359pub enum TypeExpr {
360 Named(String),
363 Union(Vec<TypeExpr>),
365 Shape(Vec<ShapeField>),
367 List(Box<TypeExpr>),
369 DictType(Box<TypeExpr>, Box<TypeExpr>),
371 FnType {
373 params: Vec<TypeExpr>,
374 return_type: Box<TypeExpr>,
375 },
376 Never,
379}
380
381#[derive(Debug, Clone, PartialEq)]
383pub struct ShapeField {
384 pub name: String,
385 pub type_expr: TypeExpr,
386 pub optional: bool,
387}
388
389#[derive(Debug, Clone, PartialEq)]
391pub enum BindingPattern {
392 Identifier(String),
394 Dict(Vec<DictPatternField>),
396 List(Vec<ListPatternElement>),
398}
399
400#[derive(Debug, Clone, PartialEq)]
402pub struct DictPatternField {
403 pub key: String,
405 pub alias: Option<String>,
407 pub is_rest: bool,
409 pub default_value: Option<Box<SNode>>,
411}
412
413#[derive(Debug, Clone, PartialEq)]
415pub struct ListPatternElement {
416 pub name: String,
418 pub is_rest: bool,
420 pub default_value: Option<Box<SNode>>,
422}
423
424#[derive(Debug, Clone, PartialEq)]
426pub struct TypeParam {
427 pub name: String,
428}
429
430#[derive(Debug, Clone, PartialEq)]
432pub struct WhereClause {
433 pub type_name: String,
434 pub bound: String,
435}
436
437#[derive(Debug, Clone, PartialEq)]
439pub struct TypedParam {
440 pub name: String,
441 pub type_expr: Option<TypeExpr>,
442 pub default_value: Option<Box<SNode>>,
443 pub rest: bool,
445}
446
447impl TypedParam {
448 pub fn untyped(name: impl Into<String>) -> Self {
450 Self {
451 name: name.into(),
452 type_expr: None,
453 default_value: None,
454 rest: false,
455 }
456 }
457
458 pub fn typed(name: impl Into<String>, type_expr: TypeExpr) -> Self {
460 Self {
461 name: name.into(),
462 type_expr: Some(type_expr),
463 default_value: None,
464 rest: false,
465 }
466 }
467
468 pub fn names(params: &[TypedParam]) -> Vec<String> {
470 params.iter().map(|p| p.name.clone()).collect()
471 }
472
473 pub fn default_start(params: &[TypedParam]) -> Option<usize> {
475 params.iter().position(|p| p.default_value.is_some())
476 }
477}