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
77 IfElse {
79 condition: Box<SNode>,
80 then_body: Vec<SNode>,
81 else_body: Option<Vec<SNode>>,
82 },
83 ForIn {
84 pattern: BindingPattern,
85 iterable: Box<SNode>,
86 body: Vec<SNode>,
87 },
88 MatchExpr {
89 value: Box<SNode>,
90 arms: Vec<MatchArm>,
91 },
92 WhileLoop {
93 condition: Box<SNode>,
94 body: Vec<SNode>,
95 },
96 Retry {
97 count: Box<SNode>,
98 body: Vec<SNode>,
99 },
100 ReturnStmt {
101 value: Option<Box<SNode>>,
102 },
103 TryCatch {
104 body: Vec<SNode>,
105 error_var: Option<String>,
106 error_type: Option<TypeExpr>,
107 catch_body: Vec<SNode>,
108 },
109 FnDecl {
110 name: String,
111 type_params: Vec<TypeParam>,
112 params: Vec<TypedParam>,
113 return_type: Option<TypeExpr>,
114 where_clauses: Vec<WhereClause>,
115 body: Vec<SNode>,
116 is_pub: bool,
117 },
118 TypeDecl {
119 name: String,
120 type_expr: TypeExpr,
121 },
122 SpawnExpr {
123 body: Vec<SNode>,
124 },
125 DurationLiteral(u64),
127 RangeExpr {
129 start: Box<SNode>,
130 end: Box<SNode>,
131 inclusive: bool,
132 },
133 GuardStmt {
135 condition: Box<SNode>,
136 else_body: Vec<SNode>,
137 },
138 AskExpr {
140 fields: Vec<DictEntry>,
141 },
142 DeadlineBlock {
144 duration: Box<SNode>,
145 body: Vec<SNode>,
146 },
147 YieldExpr {
149 value: Option<Box<SNode>>,
150 },
151 MutexBlock {
153 body: Vec<SNode>,
154 },
155 BreakStmt,
157 ContinueStmt,
159
160 Parallel {
162 count: Box<SNode>,
163 variable: Option<String>,
164 body: Vec<SNode>,
165 },
166 ParallelMap {
167 list: Box<SNode>,
168 variable: String,
169 body: Vec<SNode>,
170 },
171
172 FunctionCall {
174 name: String,
175 args: Vec<SNode>,
176 },
177 MethodCall {
178 object: Box<SNode>,
179 method: String,
180 args: Vec<SNode>,
181 },
182 OptionalMethodCall {
184 object: Box<SNode>,
185 method: String,
186 args: Vec<SNode>,
187 },
188 PropertyAccess {
189 object: Box<SNode>,
190 property: String,
191 },
192 OptionalPropertyAccess {
194 object: Box<SNode>,
195 property: String,
196 },
197 SubscriptAccess {
198 object: Box<SNode>,
199 index: Box<SNode>,
200 },
201 SliceAccess {
202 object: Box<SNode>,
203 start: Option<Box<SNode>>,
204 end: Option<Box<SNode>>,
205 },
206 BinaryOp {
207 op: String,
208 left: Box<SNode>,
209 right: Box<SNode>,
210 },
211 UnaryOp {
212 op: String,
213 operand: Box<SNode>,
214 },
215 Ternary {
216 condition: Box<SNode>,
217 true_expr: Box<SNode>,
218 false_expr: Box<SNode>,
219 },
220 Assignment {
221 target: Box<SNode>,
222 value: Box<SNode>,
223 op: Option<String>,
225 },
226 ThrowStmt {
227 value: Box<SNode>,
228 },
229
230 EnumConstruct {
232 enum_name: String,
233 variant: String,
234 args: Vec<SNode>,
235 },
236 StructConstruct {
238 struct_name: String,
239 fields: Vec<DictEntry>,
240 },
241
242 InterpolatedString(Vec<StringSegment>),
244 StringLiteral(String),
245 IntLiteral(i64),
246 FloatLiteral(f64),
247 BoolLiteral(bool),
248 NilLiteral,
249 Identifier(String),
250 ListLiteral(Vec<SNode>),
251 DictLiteral(Vec<DictEntry>),
252 Spread(Box<SNode>),
254
255 Block(Vec<SNode>),
257 Closure {
258 params: Vec<TypedParam>,
259 body: Vec<SNode>,
260 },
261}
262
263#[derive(Debug, Clone, PartialEq)]
264pub struct MatchArm {
265 pub pattern: SNode,
266 pub body: Vec<SNode>,
267}
268
269#[derive(Debug, Clone, PartialEq)]
270pub struct DictEntry {
271 pub key: SNode,
272 pub value: SNode,
273}
274
275#[derive(Debug, Clone, PartialEq)]
277pub struct EnumVariant {
278 pub name: String,
279 pub fields: Vec<TypedParam>,
280}
281
282#[derive(Debug, Clone, PartialEq)]
284pub struct StructField {
285 pub name: String,
286 pub type_expr: Option<TypeExpr>,
287 pub optional: bool,
288}
289
290#[derive(Debug, Clone, PartialEq)]
292pub struct InterfaceMethod {
293 pub name: String,
294 pub params: Vec<TypedParam>,
295 pub return_type: Option<TypeExpr>,
296}
297
298#[derive(Debug, Clone, PartialEq)]
300pub enum TypeExpr {
301 Named(String),
304 Union(Vec<TypeExpr>),
306 Shape(Vec<ShapeField>),
308 List(Box<TypeExpr>),
310 DictType(Box<TypeExpr>, Box<TypeExpr>),
312 FnType {
314 params: Vec<TypeExpr>,
315 return_type: Box<TypeExpr>,
316 },
317}
318
319#[derive(Debug, Clone, PartialEq)]
321pub struct ShapeField {
322 pub name: String,
323 pub type_expr: TypeExpr,
324 pub optional: bool,
325}
326
327#[derive(Debug, Clone, PartialEq)]
329pub enum BindingPattern {
330 Identifier(String),
332 Dict(Vec<DictPatternField>),
334 List(Vec<ListPatternElement>),
336}
337
338#[derive(Debug, Clone, PartialEq)]
340pub struct DictPatternField {
341 pub key: String,
343 pub alias: Option<String>,
345 pub is_rest: bool,
347}
348
349#[derive(Debug, Clone, PartialEq)]
351pub struct ListPatternElement {
352 pub name: String,
354 pub is_rest: bool,
356}
357
358#[derive(Debug, Clone, PartialEq)]
360pub struct TypeParam {
361 pub name: String,
362}
363
364#[derive(Debug, Clone, PartialEq)]
366pub struct WhereClause {
367 pub type_name: String,
368 pub bound: String,
369}
370
371#[derive(Debug, Clone, PartialEq)]
373pub struct TypedParam {
374 pub name: String,
375 pub type_expr: Option<TypeExpr>,
376}
377
378impl TypedParam {
379 pub fn untyped(name: impl Into<String>) -> Self {
381 Self {
382 name: name.into(),
383 type_expr: None,
384 }
385 }
386
387 pub fn typed(name: impl Into<String>, type_expr: TypeExpr) -> Self {
389 Self {
390 name: name.into(),
391 type_expr: Some(type_expr),
392 }
393 }
394
395 pub fn names(params: &[TypedParam]) -> Vec<String> {
397 params.iter().map(|p| p.name.clone()).collect()
398 }
399}