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 AskExpr {
166 fields: Vec<DictEntry>,
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 count: Box<SNode>,
189 variable: Option<String>,
190 body: Vec<SNode>,
191 },
192 ParallelMap {
193 list: Box<SNode>,
194 variable: String,
195 body: Vec<SNode>,
196 },
197 ParallelSettle {
198 list: Box<SNode>,
199 variable: String,
200 body: Vec<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, PartialEq)]
310pub struct MatchArm {
311 pub pattern: SNode,
312 pub body: Vec<SNode>,
313}
314
315#[derive(Debug, Clone, PartialEq)]
316pub struct SelectCase {
317 pub variable: String,
318 pub channel: Box<SNode>,
319 pub body: Vec<SNode>,
320}
321
322#[derive(Debug, Clone, PartialEq)]
323pub struct DictEntry {
324 pub key: SNode,
325 pub value: SNode,
326}
327
328#[derive(Debug, Clone, PartialEq)]
330pub struct EnumVariant {
331 pub name: String,
332 pub fields: Vec<TypedParam>,
333}
334
335#[derive(Debug, Clone, PartialEq)]
337pub struct StructField {
338 pub name: String,
339 pub type_expr: Option<TypeExpr>,
340 pub optional: bool,
341}
342
343#[derive(Debug, Clone, PartialEq)]
345pub struct InterfaceMethod {
346 pub name: String,
347 pub type_params: Vec<TypeParam>,
348 pub params: Vec<TypedParam>,
349 pub return_type: Option<TypeExpr>,
350}
351
352#[derive(Debug, Clone, PartialEq)]
354pub enum TypeExpr {
355 Named(String),
358 Union(Vec<TypeExpr>),
360 Shape(Vec<ShapeField>),
362 List(Box<TypeExpr>),
364 DictType(Box<TypeExpr>, Box<TypeExpr>),
366 FnType {
368 params: Vec<TypeExpr>,
369 return_type: Box<TypeExpr>,
370 },
371 Never,
374}
375
376#[derive(Debug, Clone, PartialEq)]
378pub struct ShapeField {
379 pub name: String,
380 pub type_expr: TypeExpr,
381 pub optional: bool,
382}
383
384#[derive(Debug, Clone, PartialEq)]
386pub enum BindingPattern {
387 Identifier(String),
389 Dict(Vec<DictPatternField>),
391 List(Vec<ListPatternElement>),
393}
394
395#[derive(Debug, Clone, PartialEq)]
397pub struct DictPatternField {
398 pub key: String,
400 pub alias: Option<String>,
402 pub is_rest: bool,
404 pub default_value: Option<Box<SNode>>,
406}
407
408#[derive(Debug, Clone, PartialEq)]
410pub struct ListPatternElement {
411 pub name: String,
413 pub is_rest: bool,
415 pub default_value: Option<Box<SNode>>,
417}
418
419#[derive(Debug, Clone, PartialEq)]
421pub struct TypeParam {
422 pub name: String,
423}
424
425#[derive(Debug, Clone, PartialEq)]
427pub struct WhereClause {
428 pub type_name: String,
429 pub bound: String,
430}
431
432#[derive(Debug, Clone, PartialEq)]
434pub struct TypedParam {
435 pub name: String,
436 pub type_expr: Option<TypeExpr>,
437 pub default_value: Option<Box<SNode>>,
438 pub rest: bool,
440}
441
442impl TypedParam {
443 pub fn untyped(name: impl Into<String>) -> Self {
445 Self {
446 name: name.into(),
447 type_expr: None,
448 default_value: None,
449 rest: false,
450 }
451 }
452
453 pub fn typed(name: impl Into<String>, type_expr: TypeExpr) -> Self {
455 Self {
456 name: name.into(),
457 type_expr: Some(type_expr),
458 default_value: None,
459 rest: false,
460 }
461 }
462
463 pub fn names(params: &[TypedParam]) -> Vec<String> {
465 params.iter().map(|p| p.name.clone()).collect()
466 }
467
468 pub fn default_start(params: &[TypedParam]) -> Option<usize> {
470 params.iter().position(|p| p.default_value.is_some())
471 }
472}