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 },
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 variants: Vec<EnumVariant>,
67 },
68 StructDecl {
69 name: String,
70 fields: Vec<StructField>,
71 },
72 InterfaceDecl {
73 name: String,
74 methods: Vec<InterfaceMethod>,
75 },
76 ImplBlock {
78 type_name: String,
79 methods: Vec<SNode>,
80 },
81
82 IfElse {
84 condition: Box<SNode>,
85 then_body: Vec<SNode>,
86 else_body: Option<Vec<SNode>>,
87 },
88 ForIn {
89 pattern: BindingPattern,
90 iterable: Box<SNode>,
91 body: Vec<SNode>,
92 },
93 MatchExpr {
94 value: Box<SNode>,
95 arms: Vec<MatchArm>,
96 },
97 WhileLoop {
98 condition: Box<SNode>,
99 body: Vec<SNode>,
100 },
101 Retry {
102 count: Box<SNode>,
103 body: Vec<SNode>,
104 },
105 ReturnStmt {
106 value: Option<Box<SNode>>,
107 },
108 TryCatch {
109 body: Vec<SNode>,
110 error_var: Option<String>,
111 error_type: Option<TypeExpr>,
112 catch_body: Vec<SNode>,
113 finally_body: Option<Vec<SNode>>,
114 },
115 TryExpr {
117 body: Vec<SNode>,
118 },
119 FnDecl {
120 name: String,
121 type_params: Vec<TypeParam>,
122 params: Vec<TypedParam>,
123 return_type: Option<TypeExpr>,
124 where_clauses: Vec<WhereClause>,
125 body: Vec<SNode>,
126 is_pub: bool,
127 },
128 TypeDecl {
129 name: String,
130 type_expr: TypeExpr,
131 },
132 SpawnExpr {
133 body: Vec<SNode>,
134 },
135 DurationLiteral(u64),
137 RangeExpr {
139 start: Box<SNode>,
140 end: Box<SNode>,
141 inclusive: bool,
142 },
143 GuardStmt {
145 condition: Box<SNode>,
146 else_body: Vec<SNode>,
147 },
148 AskExpr {
150 fields: Vec<DictEntry>,
151 },
152 DeadlineBlock {
154 duration: Box<SNode>,
155 body: Vec<SNode>,
156 },
157 YieldExpr {
159 value: Option<Box<SNode>>,
160 },
161 MutexBlock {
163 body: Vec<SNode>,
164 },
165 BreakStmt,
167 ContinueStmt,
169
170 Parallel {
172 count: Box<SNode>,
173 variable: Option<String>,
174 body: Vec<SNode>,
175 },
176 ParallelMap {
177 list: Box<SNode>,
178 variable: String,
179 body: Vec<SNode>,
180 },
181 ParallelSettle {
182 list: Box<SNode>,
183 variable: String,
184 body: Vec<SNode>,
185 },
186
187 SelectExpr {
188 cases: Vec<SelectCase>,
189 timeout: Option<(Box<SNode>, Vec<SNode>)>,
190 default_body: Option<Vec<SNode>>,
191 },
192
193 FunctionCall {
195 name: String,
196 args: Vec<SNode>,
197 },
198 MethodCall {
199 object: Box<SNode>,
200 method: String,
201 args: Vec<SNode>,
202 },
203 OptionalMethodCall {
205 object: Box<SNode>,
206 method: String,
207 args: Vec<SNode>,
208 },
209 PropertyAccess {
210 object: Box<SNode>,
211 property: String,
212 },
213 OptionalPropertyAccess {
215 object: Box<SNode>,
216 property: String,
217 },
218 SubscriptAccess {
219 object: Box<SNode>,
220 index: Box<SNode>,
221 },
222 SliceAccess {
223 object: Box<SNode>,
224 start: Option<Box<SNode>>,
225 end: Option<Box<SNode>>,
226 },
227 BinaryOp {
228 op: String,
229 left: Box<SNode>,
230 right: Box<SNode>,
231 },
232 UnaryOp {
233 op: String,
234 operand: Box<SNode>,
235 },
236 Ternary {
237 condition: Box<SNode>,
238 true_expr: Box<SNode>,
239 false_expr: Box<SNode>,
240 },
241 Assignment {
242 target: Box<SNode>,
243 value: Box<SNode>,
244 op: Option<String>,
246 },
247 ThrowStmt {
248 value: Box<SNode>,
249 },
250
251 EnumConstruct {
253 enum_name: String,
254 variant: String,
255 args: Vec<SNode>,
256 },
257 StructConstruct {
259 struct_name: String,
260 fields: Vec<DictEntry>,
261 },
262
263 InterpolatedString(Vec<StringSegment>),
265 StringLiteral(String),
266 IntLiteral(i64),
267 FloatLiteral(f64),
268 BoolLiteral(bool),
269 NilLiteral,
270 Identifier(String),
271 ListLiteral(Vec<SNode>),
272 DictLiteral(Vec<DictEntry>),
273 Spread(Box<SNode>),
275 TryOperator {
277 operand: Box<SNode>,
278 },
279
280 Block(Vec<SNode>),
282 Closure {
283 params: Vec<TypedParam>,
284 body: Vec<SNode>,
285 fn_syntax: bool,
288 },
289}
290
291#[derive(Debug, Clone, PartialEq)]
292pub struct MatchArm {
293 pub pattern: SNode,
294 pub body: Vec<SNode>,
295}
296
297#[derive(Debug, Clone, PartialEq)]
298pub struct SelectCase {
299 pub variable: String,
300 pub channel: Box<SNode>,
301 pub body: Vec<SNode>,
302}
303
304#[derive(Debug, Clone, PartialEq)]
305pub struct DictEntry {
306 pub key: SNode,
307 pub value: SNode,
308}
309
310#[derive(Debug, Clone, PartialEq)]
312pub struct EnumVariant {
313 pub name: String,
314 pub fields: Vec<TypedParam>,
315}
316
317#[derive(Debug, Clone, PartialEq)]
319pub struct StructField {
320 pub name: String,
321 pub type_expr: Option<TypeExpr>,
322 pub optional: bool,
323}
324
325#[derive(Debug, Clone, PartialEq)]
327pub struct InterfaceMethod {
328 pub name: String,
329 pub params: Vec<TypedParam>,
330 pub return_type: Option<TypeExpr>,
331}
332
333#[derive(Debug, Clone, PartialEq)]
335pub enum TypeExpr {
336 Named(String),
339 Union(Vec<TypeExpr>),
341 Shape(Vec<ShapeField>),
343 List(Box<TypeExpr>),
345 DictType(Box<TypeExpr>, Box<TypeExpr>),
347 FnType {
349 params: Vec<TypeExpr>,
350 return_type: Box<TypeExpr>,
351 },
352}
353
354#[derive(Debug, Clone, PartialEq)]
356pub struct ShapeField {
357 pub name: String,
358 pub type_expr: TypeExpr,
359 pub optional: bool,
360}
361
362#[derive(Debug, Clone, PartialEq)]
364pub enum BindingPattern {
365 Identifier(String),
367 Dict(Vec<DictPatternField>),
369 List(Vec<ListPatternElement>),
371}
372
373#[derive(Debug, Clone, PartialEq)]
375pub struct DictPatternField {
376 pub key: String,
378 pub alias: Option<String>,
380 pub is_rest: bool,
382}
383
384#[derive(Debug, Clone, PartialEq)]
386pub struct ListPatternElement {
387 pub name: String,
389 pub is_rest: bool,
391}
392
393#[derive(Debug, Clone, PartialEq)]
395pub struct TypeParam {
396 pub name: String,
397}
398
399#[derive(Debug, Clone, PartialEq)]
401pub struct WhereClause {
402 pub type_name: String,
403 pub bound: String,
404}
405
406#[derive(Debug, Clone, PartialEq)]
408pub struct TypedParam {
409 pub name: String,
410 pub type_expr: Option<TypeExpr>,
411 pub default_value: Option<Box<SNode>>,
412}
413
414impl TypedParam {
415 pub fn untyped(name: impl Into<String>) -> Self {
417 Self {
418 name: name.into(),
419 type_expr: None,
420 default_value: None,
421 }
422 }
423
424 pub fn typed(name: impl Into<String>, type_expr: TypeExpr) -> Self {
426 Self {
427 name: name.into(),
428 type_expr: Some(type_expr),
429 default_value: None,
430 }
431 }
432
433 pub fn names(params: &[TypedParam]) -> Vec<String> {
435 params.iter().map(|p| p.name.clone()).collect()
436 }
437
438 pub fn default_start(params: &[TypedParam]) -> Option<usize> {
440 params.iter().position(|p| p.default_value.is_some())
441 }
442}