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 {
35 name: String,
36 params: Vec<String>,
37 body: Vec<SNode>,
38 extends: Option<String>,
39 is_pub: bool,
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 type_params: Vec<TypeParam>,
67 variants: Vec<EnumVariant>,
68 is_pub: bool,
69 },
70 StructDecl {
71 name: String,
72 type_params: Vec<TypeParam>,
73 fields: Vec<StructField>,
74 is_pub: bool,
75 },
76 InterfaceDecl {
77 name: String,
78 type_params: Vec<TypeParam>,
79 associated_types: Vec<(String, Option<TypeExpr>)>,
80 methods: Vec<InterfaceMethod>,
81 },
82 ImplBlock {
84 type_name: String,
85 methods: Vec<SNode>,
86 },
87
88 IfElse {
89 condition: Box<SNode>,
90 then_body: Vec<SNode>,
91 else_body: Option<Vec<SNode>>,
92 },
93 ForIn {
94 pattern: BindingPattern,
95 iterable: Box<SNode>,
96 body: Vec<SNode>,
97 },
98 MatchExpr {
99 value: Box<SNode>,
100 arms: Vec<MatchArm>,
101 },
102 WhileLoop {
103 condition: Box<SNode>,
104 body: Vec<SNode>,
105 },
106 Retry {
107 count: Box<SNode>,
108 body: Vec<SNode>,
109 },
110 ReturnStmt {
111 value: Option<Box<SNode>>,
112 },
113 TryCatch {
114 body: Vec<SNode>,
115 error_var: Option<String>,
116 error_type: Option<TypeExpr>,
117 catch_body: Vec<SNode>,
118 finally_body: Option<Vec<SNode>>,
119 },
120 TryExpr {
122 body: Vec<SNode>,
123 },
124 FnDecl {
125 name: String,
126 type_params: Vec<TypeParam>,
127 params: Vec<TypedParam>,
128 return_type: Option<TypeExpr>,
129 where_clauses: Vec<WhereClause>,
130 body: Vec<SNode>,
131 is_pub: bool,
132 },
133 ToolDecl {
134 name: String,
135 description: Option<String>,
136 params: Vec<TypedParam>,
137 return_type: Option<TypeExpr>,
138 body: Vec<SNode>,
139 is_pub: bool,
140 },
141 TypeDecl {
142 name: String,
143 type_params: Vec<TypeParam>,
144 type_expr: TypeExpr,
145 },
146 SpawnExpr {
147 body: Vec<SNode>,
148 },
149 DurationLiteral(u64),
151 RangeExpr {
153 start: Box<SNode>,
154 end: Box<SNode>,
155 inclusive: bool,
156 },
157 GuardStmt {
159 condition: Box<SNode>,
160 else_body: Vec<SNode>,
161 },
162 RequireStmt {
163 condition: Box<SNode>,
164 message: Option<Box<SNode>>,
165 },
166 DeferStmt {
168 body: Vec<SNode>,
169 },
170 DeadlineBlock {
172 duration: Box<SNode>,
173 body: Vec<SNode>,
174 },
175 YieldExpr {
177 value: Option<Box<SNode>>,
178 },
179 MutexBlock {
181 body: Vec<SNode>,
182 },
183 BreakStmt,
185 ContinueStmt,
187
188 Parallel {
189 mode: ParallelMode,
190 expr: Box<SNode>,
192 variable: Option<String>,
193 body: Vec<SNode>,
194 options: Vec<(String, SNode)>,
199 },
200
201 SelectExpr {
202 cases: Vec<SelectCase>,
203 timeout: Option<(Box<SNode>, Vec<SNode>)>,
204 default_body: Option<Vec<SNode>>,
205 },
206
207 FunctionCall {
208 name: String,
209 args: Vec<SNode>,
210 },
211 MethodCall {
212 object: Box<SNode>,
213 method: String,
214 args: Vec<SNode>,
215 },
216 OptionalMethodCall {
218 object: Box<SNode>,
219 method: String,
220 args: Vec<SNode>,
221 },
222 PropertyAccess {
223 object: Box<SNode>,
224 property: String,
225 },
226 OptionalPropertyAccess {
228 object: Box<SNode>,
229 property: String,
230 },
231 SubscriptAccess {
232 object: Box<SNode>,
233 index: Box<SNode>,
234 },
235 SliceAccess {
236 object: Box<SNode>,
237 start: Option<Box<SNode>>,
238 end: Option<Box<SNode>>,
239 },
240 BinaryOp {
241 op: String,
242 left: Box<SNode>,
243 right: Box<SNode>,
244 },
245 UnaryOp {
246 op: String,
247 operand: Box<SNode>,
248 },
249 Ternary {
250 condition: Box<SNode>,
251 true_expr: Box<SNode>,
252 false_expr: Box<SNode>,
253 },
254 Assignment {
255 target: Box<SNode>,
256 value: Box<SNode>,
257 op: Option<String>,
259 },
260 ThrowStmt {
261 value: Box<SNode>,
262 },
263
264 EnumConstruct {
266 enum_name: String,
267 variant: String,
268 args: Vec<SNode>,
269 },
270 StructConstruct {
272 struct_name: String,
273 fields: Vec<DictEntry>,
274 },
275
276 InterpolatedString(Vec<StringSegment>),
277 StringLiteral(String),
278 RawStringLiteral(String),
280 IntLiteral(i64),
281 FloatLiteral(f64),
282 BoolLiteral(bool),
283 NilLiteral,
284 Identifier(String),
285 ListLiteral(Vec<SNode>),
286 DictLiteral(Vec<DictEntry>),
287 Spread(Box<SNode>),
289 TryOperator {
291 operand: Box<SNode>,
292 },
293 TryStar {
301 operand: Box<SNode>,
302 },
303
304 Block(Vec<SNode>),
305 Closure {
306 params: Vec<TypedParam>,
307 body: Vec<SNode>,
308 fn_syntax: bool,
311 },
312}
313
314#[derive(Debug, Clone, Copy, PartialEq)]
316pub enum ParallelMode {
317 Count,
319 Each,
321 Settle,
323}
324
325#[derive(Debug, Clone, PartialEq)]
326pub struct MatchArm {
327 pub pattern: SNode,
328 pub guard: Option<Box<SNode>>,
330 pub body: Vec<SNode>,
331}
332
333#[derive(Debug, Clone, PartialEq)]
334pub struct SelectCase {
335 pub variable: String,
336 pub channel: Box<SNode>,
337 pub body: Vec<SNode>,
338}
339
340#[derive(Debug, Clone, PartialEq)]
341pub struct DictEntry {
342 pub key: SNode,
343 pub value: SNode,
344}
345
346#[derive(Debug, Clone, PartialEq)]
348pub struct EnumVariant {
349 pub name: String,
350 pub fields: Vec<TypedParam>,
351}
352
353#[derive(Debug, Clone, PartialEq)]
355pub struct StructField {
356 pub name: String,
357 pub type_expr: Option<TypeExpr>,
358 pub optional: bool,
359}
360
361#[derive(Debug, Clone, PartialEq)]
363pub struct InterfaceMethod {
364 pub name: String,
365 pub type_params: Vec<TypeParam>,
366 pub params: Vec<TypedParam>,
367 pub return_type: Option<TypeExpr>,
368}
369
370#[derive(Debug, Clone, PartialEq)]
372pub enum TypeExpr {
373 Named(String),
376 Union(Vec<TypeExpr>),
378 Shape(Vec<ShapeField>),
380 List(Box<TypeExpr>),
382 DictType(Box<TypeExpr>, Box<TypeExpr>),
384 Iter(Box<TypeExpr>),
387 Applied { name: String, args: Vec<TypeExpr> },
389 FnType {
391 params: Vec<TypeExpr>,
392 return_type: Box<TypeExpr>,
393 },
394 Never,
397 LitString(String),
400 LitInt(i64),
402}
403
404#[derive(Debug, Clone, PartialEq)]
406pub struct ShapeField {
407 pub name: String,
408 pub type_expr: TypeExpr,
409 pub optional: bool,
410}
411
412#[derive(Debug, Clone, PartialEq)]
414pub enum BindingPattern {
415 Identifier(String),
417 Dict(Vec<DictPatternField>),
419 List(Vec<ListPatternElement>),
421 Pair(String, String),
424}
425
426#[derive(Debug, Clone, PartialEq)]
428pub struct DictPatternField {
429 pub key: String,
431 pub alias: Option<String>,
433 pub is_rest: bool,
435 pub default_value: Option<Box<SNode>>,
437}
438
439#[derive(Debug, Clone, PartialEq)]
441pub struct ListPatternElement {
442 pub name: String,
444 pub is_rest: bool,
446 pub default_value: Option<Box<SNode>>,
448}
449
450#[derive(Debug, Clone, Copy, PartialEq, Eq)]
462pub enum Variance {
463 Invariant,
464 Covariant,
465 Contravariant,
466}
467
468#[derive(Debug, Clone, PartialEq)]
470pub struct TypeParam {
471 pub name: String,
472 pub variance: Variance,
473}
474
475impl TypeParam {
476 pub fn invariant(name: impl Into<String>) -> Self {
479 Self {
480 name: name.into(),
481 variance: Variance::Invariant,
482 }
483 }
484}
485
486#[derive(Debug, Clone, PartialEq)]
488pub struct WhereClause {
489 pub type_name: String,
490 pub bound: String,
491}
492
493#[derive(Debug, Clone, PartialEq)]
495pub struct TypedParam {
496 pub name: String,
497 pub type_expr: Option<TypeExpr>,
498 pub default_value: Option<Box<SNode>>,
499 pub rest: bool,
501}
502
503impl TypedParam {
504 pub fn untyped(name: impl Into<String>) -> Self {
506 Self {
507 name: name.into(),
508 type_expr: None,
509 default_value: None,
510 rest: false,
511 }
512 }
513
514 pub fn typed(name: impl Into<String>, type_expr: TypeExpr) -> Self {
516 Self {
517 name: name.into(),
518 type_expr: Some(type_expr),
519 default_value: None,
520 rest: false,
521 }
522 }
523
524 pub fn names(params: &[TypedParam]) -> Vec<String> {
526 params.iter().map(|p| p.name.clone()).collect()
527 }
528
529 pub fn default_start(params: &[TypedParam]) -> Option<usize> {
531 params.iter().position(|p| p.default_value.is_some())
532 }
533}