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 IntLiteral(i64),
283 FloatLiteral(f64),
284 BoolLiteral(bool),
285 NilLiteral,
286 Identifier(String),
287 ListLiteral(Vec<SNode>),
288 DictLiteral(Vec<DictEntry>),
289 Spread(Box<SNode>),
291 TryOperator {
293 operand: Box<SNode>,
294 },
295
296 Block(Vec<SNode>),
298 Closure {
299 params: Vec<TypedParam>,
300 body: Vec<SNode>,
301 fn_syntax: bool,
304 },
305}
306
307#[derive(Debug, Clone, PartialEq)]
308pub struct MatchArm {
309 pub pattern: SNode,
310 pub body: Vec<SNode>,
311}
312
313#[derive(Debug, Clone, PartialEq)]
314pub struct SelectCase {
315 pub variable: String,
316 pub channel: Box<SNode>,
317 pub body: Vec<SNode>,
318}
319
320#[derive(Debug, Clone, PartialEq)]
321pub struct DictEntry {
322 pub key: SNode,
323 pub value: SNode,
324}
325
326#[derive(Debug, Clone, PartialEq)]
328pub struct EnumVariant {
329 pub name: String,
330 pub fields: Vec<TypedParam>,
331}
332
333#[derive(Debug, Clone, PartialEq)]
335pub struct StructField {
336 pub name: String,
337 pub type_expr: Option<TypeExpr>,
338 pub optional: bool,
339}
340
341#[derive(Debug, Clone, PartialEq)]
343pub struct InterfaceMethod {
344 pub name: String,
345 pub type_params: Vec<TypeParam>,
346 pub params: Vec<TypedParam>,
347 pub return_type: Option<TypeExpr>,
348}
349
350#[derive(Debug, Clone, PartialEq)]
352pub enum TypeExpr {
353 Named(String),
356 Union(Vec<TypeExpr>),
358 Shape(Vec<ShapeField>),
360 List(Box<TypeExpr>),
362 DictType(Box<TypeExpr>, Box<TypeExpr>),
364 FnType {
366 params: Vec<TypeExpr>,
367 return_type: Box<TypeExpr>,
368 },
369}
370
371#[derive(Debug, Clone, PartialEq)]
373pub struct ShapeField {
374 pub name: String,
375 pub type_expr: TypeExpr,
376 pub optional: bool,
377}
378
379#[derive(Debug, Clone, PartialEq)]
381pub enum BindingPattern {
382 Identifier(String),
384 Dict(Vec<DictPatternField>),
386 List(Vec<ListPatternElement>),
388}
389
390#[derive(Debug, Clone, PartialEq)]
392pub struct DictPatternField {
393 pub key: String,
395 pub alias: Option<String>,
397 pub is_rest: bool,
399}
400
401#[derive(Debug, Clone, PartialEq)]
403pub struct ListPatternElement {
404 pub name: String,
406 pub is_rest: bool,
408}
409
410#[derive(Debug, Clone, PartialEq)]
412pub struct TypeParam {
413 pub name: String,
414}
415
416#[derive(Debug, Clone, PartialEq)]
418pub struct WhereClause {
419 pub type_name: String,
420 pub bound: String,
421}
422
423#[derive(Debug, Clone, PartialEq)]
425pub struct TypedParam {
426 pub name: String,
427 pub type_expr: Option<TypeExpr>,
428 pub default_value: Option<Box<SNode>>,
429}
430
431impl TypedParam {
432 pub fn untyped(name: impl Into<String>) -> Self {
434 Self {
435 name: name.into(),
436 type_expr: None,
437 default_value: None,
438 }
439 }
440
441 pub fn typed(name: impl Into<String>, type_expr: TypeExpr) -> Self {
443 Self {
444 name: name.into(),
445 type_expr: Some(type_expr),
446 default_value: None,
447 }
448 }
449
450 pub fn names(params: &[TypedParam]) -> Vec<String> {
452 params.iter().map(|p| p.name.clone()).collect()
453 }
454
455 pub fn default_start(params: &[TypedParam]) -> Option<usize> {
457 params.iter().position(|p| p.default_value.is_some())
458 }
459}