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 RequireStmt {
149 condition: Box<SNode>,
150 message: Option<Box<SNode>>,
151 },
152 AskExpr {
154 fields: Vec<DictEntry>,
155 },
156 DeadlineBlock {
158 duration: Box<SNode>,
159 body: Vec<SNode>,
160 },
161 YieldExpr {
163 value: Option<Box<SNode>>,
164 },
165 MutexBlock {
167 body: Vec<SNode>,
168 },
169 BreakStmt,
171 ContinueStmt,
173
174 Parallel {
176 count: Box<SNode>,
177 variable: Option<String>,
178 body: Vec<SNode>,
179 },
180 ParallelMap {
181 list: Box<SNode>,
182 variable: String,
183 body: Vec<SNode>,
184 },
185 ParallelSettle {
186 list: Box<SNode>,
187 variable: String,
188 body: Vec<SNode>,
189 },
190
191 SelectExpr {
192 cases: Vec<SelectCase>,
193 timeout: Option<(Box<SNode>, Vec<SNode>)>,
194 default_body: Option<Vec<SNode>>,
195 },
196
197 FunctionCall {
199 name: String,
200 args: Vec<SNode>,
201 },
202 MethodCall {
203 object: Box<SNode>,
204 method: String,
205 args: Vec<SNode>,
206 },
207 OptionalMethodCall {
209 object: Box<SNode>,
210 method: String,
211 args: Vec<SNode>,
212 },
213 PropertyAccess {
214 object: Box<SNode>,
215 property: String,
216 },
217 OptionalPropertyAccess {
219 object: Box<SNode>,
220 property: String,
221 },
222 SubscriptAccess {
223 object: Box<SNode>,
224 index: Box<SNode>,
225 },
226 SliceAccess {
227 object: Box<SNode>,
228 start: Option<Box<SNode>>,
229 end: Option<Box<SNode>>,
230 },
231 BinaryOp {
232 op: String,
233 left: Box<SNode>,
234 right: Box<SNode>,
235 },
236 UnaryOp {
237 op: String,
238 operand: Box<SNode>,
239 },
240 Ternary {
241 condition: Box<SNode>,
242 true_expr: Box<SNode>,
243 false_expr: Box<SNode>,
244 },
245 Assignment {
246 target: Box<SNode>,
247 value: Box<SNode>,
248 op: Option<String>,
250 },
251 ThrowStmt {
252 value: Box<SNode>,
253 },
254
255 EnumConstruct {
257 enum_name: String,
258 variant: String,
259 args: Vec<SNode>,
260 },
261 StructConstruct {
263 struct_name: String,
264 fields: Vec<DictEntry>,
265 },
266
267 InterpolatedString(Vec<StringSegment>),
269 StringLiteral(String),
270 IntLiteral(i64),
271 FloatLiteral(f64),
272 BoolLiteral(bool),
273 NilLiteral,
274 Identifier(String),
275 ListLiteral(Vec<SNode>),
276 DictLiteral(Vec<DictEntry>),
277 Spread(Box<SNode>),
279 TryOperator {
281 operand: Box<SNode>,
282 },
283
284 Block(Vec<SNode>),
286 Closure {
287 params: Vec<TypedParam>,
288 body: Vec<SNode>,
289 fn_syntax: bool,
292 },
293}
294
295#[derive(Debug, Clone, PartialEq)]
296pub struct MatchArm {
297 pub pattern: SNode,
298 pub body: Vec<SNode>,
299}
300
301#[derive(Debug, Clone, PartialEq)]
302pub struct SelectCase {
303 pub variable: String,
304 pub channel: Box<SNode>,
305 pub body: Vec<SNode>,
306}
307
308#[derive(Debug, Clone, PartialEq)]
309pub struct DictEntry {
310 pub key: SNode,
311 pub value: SNode,
312}
313
314#[derive(Debug, Clone, PartialEq)]
316pub struct EnumVariant {
317 pub name: String,
318 pub fields: Vec<TypedParam>,
319}
320
321#[derive(Debug, Clone, PartialEq)]
323pub struct StructField {
324 pub name: String,
325 pub type_expr: Option<TypeExpr>,
326 pub optional: bool,
327}
328
329#[derive(Debug, Clone, PartialEq)]
331pub struct InterfaceMethod {
332 pub name: String,
333 pub params: Vec<TypedParam>,
334 pub return_type: Option<TypeExpr>,
335}
336
337#[derive(Debug, Clone, PartialEq)]
339pub enum TypeExpr {
340 Named(String),
343 Union(Vec<TypeExpr>),
345 Shape(Vec<ShapeField>),
347 List(Box<TypeExpr>),
349 DictType(Box<TypeExpr>, Box<TypeExpr>),
351 FnType {
353 params: Vec<TypeExpr>,
354 return_type: Box<TypeExpr>,
355 },
356}
357
358#[derive(Debug, Clone, PartialEq)]
360pub struct ShapeField {
361 pub name: String,
362 pub type_expr: TypeExpr,
363 pub optional: bool,
364}
365
366#[derive(Debug, Clone, PartialEq)]
368pub enum BindingPattern {
369 Identifier(String),
371 Dict(Vec<DictPatternField>),
373 List(Vec<ListPatternElement>),
375}
376
377#[derive(Debug, Clone, PartialEq)]
379pub struct DictPatternField {
380 pub key: String,
382 pub alias: Option<String>,
384 pub is_rest: bool,
386}
387
388#[derive(Debug, Clone, PartialEq)]
390pub struct ListPatternElement {
391 pub name: String,
393 pub is_rest: bool,
395}
396
397#[derive(Debug, Clone, PartialEq)]
399pub struct TypeParam {
400 pub name: String,
401}
402
403#[derive(Debug, Clone, PartialEq)]
405pub struct WhereClause {
406 pub type_name: String,
407 pub bound: String,
408}
409
410#[derive(Debug, Clone, PartialEq)]
412pub struct TypedParam {
413 pub name: String,
414 pub type_expr: Option<TypeExpr>,
415 pub default_value: Option<Box<SNode>>,
416}
417
418impl TypedParam {
419 pub fn untyped(name: impl Into<String>) -> Self {
421 Self {
422 name: name.into(),
423 type_expr: None,
424 default_value: None,
425 }
426 }
427
428 pub fn typed(name: impl Into<String>, type_expr: TypeExpr) -> Self {
430 Self {
431 name: name.into(),
432 type_expr: Some(type_expr),
433 default_value: None,
434 }
435 }
436
437 pub fn names(params: &[TypedParam]) -> Vec<String> {
439 params.iter().map(|p| p.name.clone()).collect()
440 }
441
442 pub fn default_start(params: &[TypedParam]) -> Option<usize> {
444 params.iter().position(|p| p.default_value.is_some())
445 }
446}