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_expr: TypeExpr,
144 },
145 SpawnExpr {
146 body: Vec<SNode>,
147 },
148 DurationLiteral(u64),
150 RangeExpr {
152 start: Box<SNode>,
153 end: Box<SNode>,
154 inclusive: bool,
155 },
156 GuardStmt {
158 condition: Box<SNode>,
159 else_body: Vec<SNode>,
160 },
161 RequireStmt {
162 condition: Box<SNode>,
163 message: Option<Box<SNode>>,
164 },
165 DeferStmt {
167 body: Vec<SNode>,
168 },
169 DeadlineBlock {
171 duration: Box<SNode>,
172 body: Vec<SNode>,
173 },
174 YieldExpr {
176 value: Option<Box<SNode>>,
177 },
178 MutexBlock {
180 body: Vec<SNode>,
181 },
182 BreakStmt,
184 ContinueStmt,
186
187 Parallel {
188 mode: ParallelMode,
189 expr: Box<SNode>,
191 variable: Option<String>,
192 body: Vec<SNode>,
193 options: Vec<(String, SNode)>,
198 },
199
200 SelectExpr {
201 cases: Vec<SelectCase>,
202 timeout: Option<(Box<SNode>, Vec<SNode>)>,
203 default_body: Option<Vec<SNode>>,
204 },
205
206 FunctionCall {
207 name: String,
208 args: Vec<SNode>,
209 },
210 MethodCall {
211 object: Box<SNode>,
212 method: String,
213 args: Vec<SNode>,
214 },
215 OptionalMethodCall {
217 object: Box<SNode>,
218 method: String,
219 args: Vec<SNode>,
220 },
221 PropertyAccess {
222 object: Box<SNode>,
223 property: String,
224 },
225 OptionalPropertyAccess {
227 object: Box<SNode>,
228 property: String,
229 },
230 SubscriptAccess {
231 object: Box<SNode>,
232 index: Box<SNode>,
233 },
234 SliceAccess {
235 object: Box<SNode>,
236 start: Option<Box<SNode>>,
237 end: Option<Box<SNode>>,
238 },
239 BinaryOp {
240 op: String,
241 left: Box<SNode>,
242 right: Box<SNode>,
243 },
244 UnaryOp {
245 op: String,
246 operand: Box<SNode>,
247 },
248 Ternary {
249 condition: Box<SNode>,
250 true_expr: Box<SNode>,
251 false_expr: Box<SNode>,
252 },
253 Assignment {
254 target: Box<SNode>,
255 value: Box<SNode>,
256 op: Option<String>,
258 },
259 ThrowStmt {
260 value: Box<SNode>,
261 },
262
263 EnumConstruct {
265 enum_name: String,
266 variant: String,
267 args: Vec<SNode>,
268 },
269 StructConstruct {
271 struct_name: String,
272 fields: Vec<DictEntry>,
273 },
274
275 InterpolatedString(Vec<StringSegment>),
276 StringLiteral(String),
277 RawStringLiteral(String),
279 IntLiteral(i64),
280 FloatLiteral(f64),
281 BoolLiteral(bool),
282 NilLiteral,
283 Identifier(String),
284 ListLiteral(Vec<SNode>),
285 DictLiteral(Vec<DictEntry>),
286 Spread(Box<SNode>),
288 TryOperator {
290 operand: Box<SNode>,
291 },
292
293 Block(Vec<SNode>),
294 Closure {
295 params: Vec<TypedParam>,
296 body: Vec<SNode>,
297 fn_syntax: bool,
300 },
301}
302
303#[derive(Debug, Clone, Copy, PartialEq)]
305pub enum ParallelMode {
306 Count,
308 Each,
310 Settle,
312}
313
314#[derive(Debug, Clone, PartialEq)]
315pub struct MatchArm {
316 pub pattern: SNode,
317 pub guard: Option<Box<SNode>>,
319 pub body: Vec<SNode>,
320}
321
322#[derive(Debug, Clone, PartialEq)]
323pub struct SelectCase {
324 pub variable: String,
325 pub channel: Box<SNode>,
326 pub body: Vec<SNode>,
327}
328
329#[derive(Debug, Clone, PartialEq)]
330pub struct DictEntry {
331 pub key: SNode,
332 pub value: SNode,
333}
334
335#[derive(Debug, Clone, PartialEq)]
337pub struct EnumVariant {
338 pub name: String,
339 pub fields: Vec<TypedParam>,
340}
341
342#[derive(Debug, Clone, PartialEq)]
344pub struct StructField {
345 pub name: String,
346 pub type_expr: Option<TypeExpr>,
347 pub optional: bool,
348}
349
350#[derive(Debug, Clone, PartialEq)]
352pub struct InterfaceMethod {
353 pub name: String,
354 pub type_params: Vec<TypeParam>,
355 pub params: Vec<TypedParam>,
356 pub return_type: Option<TypeExpr>,
357}
358
359#[derive(Debug, Clone, PartialEq)]
361pub enum TypeExpr {
362 Named(String),
365 Union(Vec<TypeExpr>),
367 Shape(Vec<ShapeField>),
369 List(Box<TypeExpr>),
371 DictType(Box<TypeExpr>, Box<TypeExpr>),
373 Iter(Box<TypeExpr>),
376 Applied { name: String, args: Vec<TypeExpr> },
378 FnType {
380 params: Vec<TypeExpr>,
381 return_type: Box<TypeExpr>,
382 },
383 Never,
386}
387
388#[derive(Debug, Clone, PartialEq)]
390pub struct ShapeField {
391 pub name: String,
392 pub type_expr: TypeExpr,
393 pub optional: bool,
394}
395
396#[derive(Debug, Clone, PartialEq)]
398pub enum BindingPattern {
399 Identifier(String),
401 Dict(Vec<DictPatternField>),
403 List(Vec<ListPatternElement>),
405 Pair(String, String),
408}
409
410#[derive(Debug, Clone, PartialEq)]
412pub struct DictPatternField {
413 pub key: String,
415 pub alias: Option<String>,
417 pub is_rest: bool,
419 pub default_value: Option<Box<SNode>>,
421}
422
423#[derive(Debug, Clone, PartialEq)]
425pub struct ListPatternElement {
426 pub name: String,
428 pub is_rest: bool,
430 pub default_value: Option<Box<SNode>>,
432}
433
434#[derive(Debug, Clone, PartialEq)]
436pub struct TypeParam {
437 pub name: String,
438}
439
440#[derive(Debug, Clone, PartialEq)]
442pub struct WhereClause {
443 pub type_name: String,
444 pub bound: String,
445}
446
447#[derive(Debug, Clone, PartialEq)]
449pub struct TypedParam {
450 pub name: String,
451 pub type_expr: Option<TypeExpr>,
452 pub default_value: Option<Box<SNode>>,
453 pub rest: bool,
455}
456
457impl TypedParam {
458 pub fn untyped(name: impl Into<String>) -> Self {
460 Self {
461 name: name.into(),
462 type_expr: None,
463 default_value: None,
464 rest: false,
465 }
466 }
467
468 pub fn typed(name: impl Into<String>, type_expr: TypeExpr) -> Self {
470 Self {
471 name: name.into(),
472 type_expr: Some(type_expr),
473 default_value: None,
474 rest: false,
475 }
476 }
477
478 pub fn names(params: &[TypedParam]) -> Vec<String> {
480 params.iter().map(|p| p.name.clone()).collect()
481 }
482
483 pub fn default_start(params: &[TypedParam]) -> Option<usize> {
485 params.iter().position(|p| p.default_value.is_some())
486 }
487}