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 FnDecl {
116 name: String,
117 type_params: Vec<TypeParam>,
118 params: Vec<TypedParam>,
119 return_type: Option<TypeExpr>,
120 where_clauses: Vec<WhereClause>,
121 body: Vec<SNode>,
122 is_pub: bool,
123 },
124 TypeDecl {
125 name: String,
126 type_expr: TypeExpr,
127 },
128 SpawnExpr {
129 body: Vec<SNode>,
130 },
131 DurationLiteral(u64),
133 RangeExpr {
135 start: Box<SNode>,
136 end: Box<SNode>,
137 inclusive: bool,
138 },
139 GuardStmt {
141 condition: Box<SNode>,
142 else_body: Vec<SNode>,
143 },
144 AskExpr {
146 fields: Vec<DictEntry>,
147 },
148 DeadlineBlock {
150 duration: Box<SNode>,
151 body: Vec<SNode>,
152 },
153 YieldExpr {
155 value: Option<Box<SNode>>,
156 },
157 MutexBlock {
159 body: Vec<SNode>,
160 },
161 BreakStmt,
163 ContinueStmt,
165
166 Parallel {
168 count: Box<SNode>,
169 variable: Option<String>,
170 body: Vec<SNode>,
171 },
172 ParallelMap {
173 list: Box<SNode>,
174 variable: String,
175 body: Vec<SNode>,
176 },
177
178 SelectExpr {
179 cases: Vec<SelectCase>,
180 timeout: Option<(Box<SNode>, Vec<SNode>)>,
181 default_body: Option<Vec<SNode>>,
182 },
183
184 FunctionCall {
186 name: String,
187 args: Vec<SNode>,
188 },
189 MethodCall {
190 object: Box<SNode>,
191 method: String,
192 args: Vec<SNode>,
193 },
194 OptionalMethodCall {
196 object: Box<SNode>,
197 method: String,
198 args: Vec<SNode>,
199 },
200 PropertyAccess {
201 object: Box<SNode>,
202 property: String,
203 },
204 OptionalPropertyAccess {
206 object: Box<SNode>,
207 property: String,
208 },
209 SubscriptAccess {
210 object: Box<SNode>,
211 index: Box<SNode>,
212 },
213 SliceAccess {
214 object: Box<SNode>,
215 start: Option<Box<SNode>>,
216 end: Option<Box<SNode>>,
217 },
218 BinaryOp {
219 op: String,
220 left: Box<SNode>,
221 right: Box<SNode>,
222 },
223 UnaryOp {
224 op: String,
225 operand: Box<SNode>,
226 },
227 Ternary {
228 condition: Box<SNode>,
229 true_expr: Box<SNode>,
230 false_expr: Box<SNode>,
231 },
232 Assignment {
233 target: Box<SNode>,
234 value: Box<SNode>,
235 op: Option<String>,
237 },
238 ThrowStmt {
239 value: Box<SNode>,
240 },
241
242 EnumConstruct {
244 enum_name: String,
245 variant: String,
246 args: Vec<SNode>,
247 },
248 StructConstruct {
250 struct_name: String,
251 fields: Vec<DictEntry>,
252 },
253
254 InterpolatedString(Vec<StringSegment>),
256 StringLiteral(String),
257 IntLiteral(i64),
258 FloatLiteral(f64),
259 BoolLiteral(bool),
260 NilLiteral,
261 Identifier(String),
262 ListLiteral(Vec<SNode>),
263 DictLiteral(Vec<DictEntry>),
264 Spread(Box<SNode>),
266 TryOperator {
268 operand: Box<SNode>,
269 },
270
271 Block(Vec<SNode>),
273 Closure {
274 params: Vec<TypedParam>,
275 body: Vec<SNode>,
276 },
277}
278
279#[derive(Debug, Clone, PartialEq)]
280pub struct MatchArm {
281 pub pattern: SNode,
282 pub body: Vec<SNode>,
283}
284
285#[derive(Debug, Clone, PartialEq)]
286pub struct SelectCase {
287 pub variable: String,
288 pub channel: Box<SNode>,
289 pub body: Vec<SNode>,
290}
291
292#[derive(Debug, Clone, PartialEq)]
293pub struct DictEntry {
294 pub key: SNode,
295 pub value: SNode,
296}
297
298#[derive(Debug, Clone, PartialEq)]
300pub struct EnumVariant {
301 pub name: String,
302 pub fields: Vec<TypedParam>,
303}
304
305#[derive(Debug, Clone, PartialEq)]
307pub struct StructField {
308 pub name: String,
309 pub type_expr: Option<TypeExpr>,
310 pub optional: bool,
311}
312
313#[derive(Debug, Clone, PartialEq)]
315pub struct InterfaceMethod {
316 pub name: String,
317 pub params: Vec<TypedParam>,
318 pub return_type: Option<TypeExpr>,
319}
320
321#[derive(Debug, Clone, PartialEq)]
323pub enum TypeExpr {
324 Named(String),
327 Union(Vec<TypeExpr>),
329 Shape(Vec<ShapeField>),
331 List(Box<TypeExpr>),
333 DictType(Box<TypeExpr>, Box<TypeExpr>),
335 FnType {
337 params: Vec<TypeExpr>,
338 return_type: Box<TypeExpr>,
339 },
340}
341
342#[derive(Debug, Clone, PartialEq)]
344pub struct ShapeField {
345 pub name: String,
346 pub type_expr: TypeExpr,
347 pub optional: bool,
348}
349
350#[derive(Debug, Clone, PartialEq)]
352pub enum BindingPattern {
353 Identifier(String),
355 Dict(Vec<DictPatternField>),
357 List(Vec<ListPatternElement>),
359}
360
361#[derive(Debug, Clone, PartialEq)]
363pub struct DictPatternField {
364 pub key: String,
366 pub alias: Option<String>,
368 pub is_rest: bool,
370}
371
372#[derive(Debug, Clone, PartialEq)]
374pub struct ListPatternElement {
375 pub name: String,
377 pub is_rest: bool,
379}
380
381#[derive(Debug, Clone, PartialEq)]
383pub struct TypeParam {
384 pub name: String,
385}
386
387#[derive(Debug, Clone, PartialEq)]
389pub struct WhereClause {
390 pub type_name: String,
391 pub bound: String,
392}
393
394#[derive(Debug, Clone, PartialEq)]
396pub struct TypedParam {
397 pub name: String,
398 pub type_expr: Option<TypeExpr>,
399 pub default_value: Option<Box<SNode>>,
400}
401
402impl TypedParam {
403 pub fn untyped(name: impl Into<String>) -> Self {
405 Self {
406 name: name.into(),
407 type_expr: None,
408 default_value: None,
409 }
410 }
411
412 pub fn typed(name: impl Into<String>, type_expr: TypeExpr) -> Self {
414 Self {
415 name: name.into(),
416 type_expr: Some(type_expr),
417 default_value: None,
418 }
419 }
420
421 pub fn names(params: &[TypedParam]) -> Vec<String> {
423 params.iter().map(|p| p.name.clone()).collect()
424 }
425
426 pub fn default_start(params: &[TypedParam]) -> Option<usize> {
428 params.iter().position(|p| p.default_value.is_some())
429 }
430}