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 type_params: Vec<TypeParam>,
68 variants: Vec<EnumVariant>,
69 is_pub: bool,
70 },
71 StructDecl {
72 name: String,
73 type_params: Vec<TypeParam>,
74 fields: Vec<StructField>,
75 is_pub: bool,
76 },
77 InterfaceDecl {
78 name: String,
79 type_params: Vec<TypeParam>,
80 associated_types: Vec<(String, Option<TypeExpr>)>,
81 methods: Vec<InterfaceMethod>,
82 },
83 ImplBlock {
85 type_name: String,
86 methods: Vec<SNode>,
87 },
88
89 IfElse {
91 condition: Box<SNode>,
92 then_body: Vec<SNode>,
93 else_body: Option<Vec<SNode>>,
94 },
95 ForIn {
96 pattern: BindingPattern,
97 iterable: Box<SNode>,
98 body: Vec<SNode>,
99 },
100 MatchExpr {
101 value: Box<SNode>,
102 arms: Vec<MatchArm>,
103 },
104 WhileLoop {
105 condition: Box<SNode>,
106 body: Vec<SNode>,
107 },
108 Retry {
109 count: Box<SNode>,
110 body: Vec<SNode>,
111 },
112 ReturnStmt {
113 value: Option<Box<SNode>>,
114 },
115 TryCatch {
116 body: Vec<SNode>,
117 error_var: Option<String>,
118 error_type: Option<TypeExpr>,
119 catch_body: Vec<SNode>,
120 finally_body: Option<Vec<SNode>>,
121 },
122 TryExpr {
124 body: Vec<SNode>,
125 },
126 FnDecl {
127 name: String,
128 type_params: Vec<TypeParam>,
129 params: Vec<TypedParam>,
130 return_type: Option<TypeExpr>,
131 where_clauses: Vec<WhereClause>,
132 body: Vec<SNode>,
133 is_pub: bool,
134 },
135 ToolDecl {
136 name: String,
137 description: Option<String>,
138 params: Vec<TypedParam>,
139 return_type: Option<TypeExpr>,
140 body: Vec<SNode>,
141 is_pub: bool,
142 },
143 TypeDecl {
144 name: String,
145 type_expr: TypeExpr,
146 },
147 SpawnExpr {
148 body: Vec<SNode>,
149 },
150 DurationLiteral(u64),
152 RangeExpr {
154 start: Box<SNode>,
155 end: Box<SNode>,
156 inclusive: bool,
157 },
158 GuardStmt {
160 condition: Box<SNode>,
161 else_body: Vec<SNode>,
162 },
163 RequireStmt {
164 condition: Box<SNode>,
165 message: Option<Box<SNode>>,
166 },
167 DeferStmt {
169 body: Vec<SNode>,
170 },
171 DeadlineBlock {
173 duration: Box<SNode>,
174 body: Vec<SNode>,
175 },
176 YieldExpr {
178 value: Option<Box<SNode>>,
179 },
180 MutexBlock {
182 body: Vec<SNode>,
183 },
184 BreakStmt,
186 ContinueStmt,
188
189 Parallel {
191 mode: ParallelMode,
192 expr: Box<SNode>,
194 variable: Option<String>,
195 body: Vec<SNode>,
196 options: Vec<(String, SNode)>,
201 },
202
203 SelectExpr {
204 cases: Vec<SelectCase>,
205 timeout: Option<(Box<SNode>, Vec<SNode>)>,
206 default_body: Option<Vec<SNode>>,
207 },
208
209 FunctionCall {
211 name: String,
212 args: Vec<SNode>,
213 },
214 MethodCall {
215 object: Box<SNode>,
216 method: String,
217 args: Vec<SNode>,
218 },
219 OptionalMethodCall {
221 object: Box<SNode>,
222 method: String,
223 args: Vec<SNode>,
224 },
225 PropertyAccess {
226 object: Box<SNode>,
227 property: String,
228 },
229 OptionalPropertyAccess {
231 object: Box<SNode>,
232 property: String,
233 },
234 SubscriptAccess {
235 object: Box<SNode>,
236 index: Box<SNode>,
237 },
238 SliceAccess {
239 object: Box<SNode>,
240 start: Option<Box<SNode>>,
241 end: Option<Box<SNode>>,
242 },
243 BinaryOp {
244 op: String,
245 left: Box<SNode>,
246 right: Box<SNode>,
247 },
248 UnaryOp {
249 op: String,
250 operand: Box<SNode>,
251 },
252 Ternary {
253 condition: Box<SNode>,
254 true_expr: Box<SNode>,
255 false_expr: Box<SNode>,
256 },
257 Assignment {
258 target: Box<SNode>,
259 value: Box<SNode>,
260 op: Option<String>,
262 },
263 ThrowStmt {
264 value: Box<SNode>,
265 },
266
267 EnumConstruct {
269 enum_name: String,
270 variant: String,
271 args: Vec<SNode>,
272 },
273 StructConstruct {
275 struct_name: String,
276 fields: Vec<DictEntry>,
277 },
278
279 InterpolatedString(Vec<StringSegment>),
281 StringLiteral(String),
282 RawStringLiteral(String),
284 IntLiteral(i64),
285 FloatLiteral(f64),
286 BoolLiteral(bool),
287 NilLiteral,
288 Identifier(String),
289 ListLiteral(Vec<SNode>),
290 DictLiteral(Vec<DictEntry>),
291 Spread(Box<SNode>),
293 TryOperator {
295 operand: Box<SNode>,
296 },
297
298 Block(Vec<SNode>),
300 Closure {
301 params: Vec<TypedParam>,
302 body: Vec<SNode>,
303 fn_syntax: bool,
306 },
307}
308
309#[derive(Debug, Clone, Copy, PartialEq)]
311pub enum ParallelMode {
312 Count,
314 Each,
316 Settle,
318}
319
320#[derive(Debug, Clone, PartialEq)]
321pub struct MatchArm {
322 pub pattern: SNode,
323 pub guard: Option<Box<SNode>>,
325 pub body: Vec<SNode>,
326}
327
328#[derive(Debug, Clone, PartialEq)]
329pub struct SelectCase {
330 pub variable: String,
331 pub channel: Box<SNode>,
332 pub body: Vec<SNode>,
333}
334
335#[derive(Debug, Clone, PartialEq)]
336pub struct DictEntry {
337 pub key: SNode,
338 pub value: SNode,
339}
340
341#[derive(Debug, Clone, PartialEq)]
343pub struct EnumVariant {
344 pub name: String,
345 pub fields: Vec<TypedParam>,
346}
347
348#[derive(Debug, Clone, PartialEq)]
350pub struct StructField {
351 pub name: String,
352 pub type_expr: Option<TypeExpr>,
353 pub optional: bool,
354}
355
356#[derive(Debug, Clone, PartialEq)]
358pub struct InterfaceMethod {
359 pub name: String,
360 pub type_params: Vec<TypeParam>,
361 pub params: Vec<TypedParam>,
362 pub return_type: Option<TypeExpr>,
363}
364
365#[derive(Debug, Clone, PartialEq)]
367pub enum TypeExpr {
368 Named(String),
371 Union(Vec<TypeExpr>),
373 Shape(Vec<ShapeField>),
375 List(Box<TypeExpr>),
377 DictType(Box<TypeExpr>, Box<TypeExpr>),
379 Iter(Box<TypeExpr>),
382 Applied { name: String, args: Vec<TypeExpr> },
384 FnType {
386 params: Vec<TypeExpr>,
387 return_type: Box<TypeExpr>,
388 },
389 Never,
392}
393
394#[derive(Debug, Clone, PartialEq)]
396pub struct ShapeField {
397 pub name: String,
398 pub type_expr: TypeExpr,
399 pub optional: bool,
400}
401
402#[derive(Debug, Clone, PartialEq)]
404pub enum BindingPattern {
405 Identifier(String),
407 Dict(Vec<DictPatternField>),
409 List(Vec<ListPatternElement>),
411 Pair(String, String),
414}
415
416#[derive(Debug, Clone, PartialEq)]
418pub struct DictPatternField {
419 pub key: String,
421 pub alias: Option<String>,
423 pub is_rest: bool,
425 pub default_value: Option<Box<SNode>>,
427}
428
429#[derive(Debug, Clone, PartialEq)]
431pub struct ListPatternElement {
432 pub name: String,
434 pub is_rest: bool,
436 pub default_value: Option<Box<SNode>>,
438}
439
440#[derive(Debug, Clone, PartialEq)]
442pub struct TypeParam {
443 pub name: String,
444}
445
446#[derive(Debug, Clone, PartialEq)]
448pub struct WhereClause {
449 pub type_name: String,
450 pub bound: String,
451}
452
453#[derive(Debug, Clone, PartialEq)]
455pub struct TypedParam {
456 pub name: String,
457 pub type_expr: Option<TypeExpr>,
458 pub default_value: Option<Box<SNode>>,
459 pub rest: bool,
461}
462
463impl TypedParam {
464 pub fn untyped(name: impl Into<String>) -> Self {
466 Self {
467 name: name.into(),
468 type_expr: None,
469 default_value: None,
470 rest: false,
471 }
472 }
473
474 pub fn typed(name: impl Into<String>, type_expr: TypeExpr) -> Self {
476 Self {
477 name: name.into(),
478 type_expr: Some(type_expr),
479 default_value: None,
480 rest: false,
481 }
482 }
483
484 pub fn names(params: &[TypedParam]) -> Vec<String> {
486 params.iter().map(|p| p.name.clone()).collect()
487 }
488
489 pub fn default_start(params: &[TypedParam]) -> Option<usize> {
491 params.iter().position(|p| p.default_value.is_some())
492 }
493}