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 TypeDecl {
133 name: String,
134 type_expr: TypeExpr,
135 },
136 SpawnExpr {
137 body: Vec<SNode>,
138 },
139 DurationLiteral(u64),
141 RangeExpr {
143 start: Box<SNode>,
144 end: Box<SNode>,
145 inclusive: bool,
146 },
147 GuardStmt {
149 condition: Box<SNode>,
150 else_body: Vec<SNode>,
151 },
152 RequireStmt {
153 condition: Box<SNode>,
154 message: Option<Box<SNode>>,
155 },
156 AskExpr {
158 fields: Vec<DictEntry>,
159 },
160 DeadlineBlock {
162 duration: Box<SNode>,
163 body: Vec<SNode>,
164 },
165 YieldExpr {
167 value: Option<Box<SNode>>,
168 },
169 MutexBlock {
171 body: Vec<SNode>,
172 },
173 BreakStmt,
175 ContinueStmt,
177
178 Parallel {
180 count: Box<SNode>,
181 variable: Option<String>,
182 body: Vec<SNode>,
183 },
184 ParallelMap {
185 list: Box<SNode>,
186 variable: String,
187 body: Vec<SNode>,
188 },
189 ParallelSettle {
190 list: Box<SNode>,
191 variable: 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 IntLiteral(i64),
275 FloatLiteral(f64),
276 BoolLiteral(bool),
277 NilLiteral,
278 Identifier(String),
279 ListLiteral(Vec<SNode>),
280 DictLiteral(Vec<DictEntry>),
281 Spread(Box<SNode>),
283 TryOperator {
285 operand: Box<SNode>,
286 },
287
288 Block(Vec<SNode>),
290 Closure {
291 params: Vec<TypedParam>,
292 body: Vec<SNode>,
293 fn_syntax: bool,
296 },
297}
298
299#[derive(Debug, Clone, PartialEq)]
300pub struct MatchArm {
301 pub pattern: SNode,
302 pub body: Vec<SNode>,
303}
304
305#[derive(Debug, Clone, PartialEq)]
306pub struct SelectCase {
307 pub variable: String,
308 pub channel: Box<SNode>,
309 pub body: Vec<SNode>,
310}
311
312#[derive(Debug, Clone, PartialEq)]
313pub struct DictEntry {
314 pub key: SNode,
315 pub value: SNode,
316}
317
318#[derive(Debug, Clone, PartialEq)]
320pub struct EnumVariant {
321 pub name: String,
322 pub fields: Vec<TypedParam>,
323}
324
325#[derive(Debug, Clone, PartialEq)]
327pub struct StructField {
328 pub name: String,
329 pub type_expr: Option<TypeExpr>,
330 pub optional: bool,
331}
332
333#[derive(Debug, Clone, PartialEq)]
335pub struct InterfaceMethod {
336 pub name: String,
337 pub type_params: Vec<TypeParam>,
338 pub params: Vec<TypedParam>,
339 pub return_type: Option<TypeExpr>,
340}
341
342#[derive(Debug, Clone, PartialEq)]
344pub enum TypeExpr {
345 Named(String),
348 Union(Vec<TypeExpr>),
350 Shape(Vec<ShapeField>),
352 List(Box<TypeExpr>),
354 DictType(Box<TypeExpr>, Box<TypeExpr>),
356 FnType {
358 params: Vec<TypeExpr>,
359 return_type: Box<TypeExpr>,
360 },
361}
362
363#[derive(Debug, Clone, PartialEq)]
365pub struct ShapeField {
366 pub name: String,
367 pub type_expr: TypeExpr,
368 pub optional: bool,
369}
370
371#[derive(Debug, Clone, PartialEq)]
373pub enum BindingPattern {
374 Identifier(String),
376 Dict(Vec<DictPatternField>),
378 List(Vec<ListPatternElement>),
380}
381
382#[derive(Debug, Clone, PartialEq)]
384pub struct DictPatternField {
385 pub key: String,
387 pub alias: Option<String>,
389 pub is_rest: bool,
391}
392
393#[derive(Debug, Clone, PartialEq)]
395pub struct ListPatternElement {
396 pub name: String,
398 pub is_rest: bool,
400}
401
402#[derive(Debug, Clone, PartialEq)]
404pub struct TypeParam {
405 pub name: String,
406}
407
408#[derive(Debug, Clone, PartialEq)]
410pub struct WhereClause {
411 pub type_name: String,
412 pub bound: String,
413}
414
415#[derive(Debug, Clone, PartialEq)]
417pub struct TypedParam {
418 pub name: String,
419 pub type_expr: Option<TypeExpr>,
420 pub default_value: Option<Box<SNode>>,
421}
422
423impl TypedParam {
424 pub fn untyped(name: impl Into<String>) -> Self {
426 Self {
427 name: name.into(),
428 type_expr: None,
429 default_value: None,
430 }
431 }
432
433 pub fn typed(name: impl Into<String>, type_expr: TypeExpr) -> Self {
435 Self {
436 name: name.into(),
437 type_expr: Some(type_expr),
438 default_value: None,
439 }
440 }
441
442 pub fn names(params: &[TypedParam]) -> Vec<String> {
444 params.iter().map(|p| p.name.clone()).collect()
445 }
446
447 pub fn default_start(params: &[TypedParam]) -> Option<usize> {
449 params.iter().position(|p| p.default_value.is_some())
450 }
451}