1use indexmap::IndexMap;
18
19use snarkvm::prelude::{Address, TestnetV0};
20
21use leo_ast::{Expression, Intrinsic, NodeBuilder};
22use leo_errors::{Handler, ParserError, Result, TypeCheckerError};
23use leo_parser_lossless::{
24 ExpressionKind,
25 IntegerLiteralKind,
26 IntegerTypeKind,
27 LiteralKind,
28 StatementKind,
29 SyntaxKind,
30 SyntaxNode,
31 TypeKind,
32};
33use leo_span::{
34 Span,
35 Symbol,
36 sym::{self},
37};
38
39fn to_identifier(node: &SyntaxNode<'_>, builder: &NodeBuilder) -> leo_ast::Identifier {
40 let name = Symbol::intern(node.text);
41 leo_ast::Identifier { name, span: node.span, id: builder.next_id() }
42}
43
44fn path_to_parts(node: &SyntaxNode<'_>, builder: &NodeBuilder) -> Vec<leo_ast::Identifier> {
45 let mut identifiers = Vec::new();
46 let mut i = node.span.lo;
47 for text in node.text.split("::") {
48 let end = i + text.len() as u32;
49 let span = leo_span::Span { lo: i, hi: end };
50 let name = Symbol::intern(text);
51 identifiers.push(leo_ast::Identifier { name, span, id: builder.next_id() });
52 i = end + 2;
54 }
55 identifiers
56}
57
58fn to_mode(node: &SyntaxNode<'_>) -> leo_ast::Mode {
59 match node.text {
60 "constant" => leo_ast::Mode::Constant,
61 "private" => leo_ast::Mode::Private,
62 "public" => leo_ast::Mode::Public,
63 _ => leo_ast::Mode::None,
64 }
65}
66
67fn to_type(node: &SyntaxNode<'_>, builder: &NodeBuilder, handler: &Handler) -> Result<leo_ast::Type> {
68 let SyntaxKind::Type(type_kind) = node.kind else { todo!() };
69
70 let type_ = match type_kind {
71 TypeKind::Address => leo_ast::Type::Address,
72 TypeKind::Array => {
73 let [_l, type_, _s, length, _r] = &node.children[..] else {
74 panic!("Can't happen");
77 };
78 let element_type = to_type(type_, builder, handler)?;
79 let length = to_expression(length, builder, handler)?;
80 leo_ast::ArrayType { element_type: Box::new(element_type), length: Box::new(length) }.into()
81 }
82 TypeKind::Boolean => leo_ast::Type::Boolean,
83 TypeKind::Composite => {
84 let name = &node.children[0];
85 if let Some((program, name_str)) = name.text.split_once(".aleo/") {
86 let name_id = leo_ast::Identifier {
88 name: Symbol::intern(name_str),
89 span: leo_span::Span {
90 lo: name.span.lo + program.len() as u32 + 5,
91 hi: name.span.lo + name.text.len() as u32,
92 },
93 id: builder.next_id(),
94 };
95 leo_ast::CompositeType {
96 path: leo_ast::Path::new(Vec::new(), name_id, false, None, name_id.span, builder.next_id()),
97 const_arguments: Vec::new(),
98 program: Some(Symbol::intern(program)),
99 }
100 .into()
101 } else {
102 let mut path_components = path_to_parts(name, builder);
104 let mut const_arguments = Vec::new();
105 if let Some(arg_list) = node.children.get(1) {
106 const_arguments = arg_list
107 .children
108 .iter()
109 .filter(|child| matches!(child.kind, SyntaxKind::Expression(..)))
110 .map(|child| to_expression(child, builder, handler))
111 .collect::<Result<Vec<_>>>()?;
112 }
113 let identifier = path_components.pop().unwrap();
114 let path = leo_ast::Path::new(path_components, identifier, false, None, name.span, builder.next_id());
115 leo_ast::CompositeType { path, const_arguments, program: None }.into()
116 }
117 }
118 TypeKind::Field => leo_ast::Type::Field,
119 TypeKind::Future => {
120 if node.children.len() == 1 {
121 leo_ast::FutureType::default().into()
122 } else {
123 let types = node
124 .children
125 .iter()
126 .filter(|child| matches!(child.kind, SyntaxKind::Type(..)))
127 .map(|child| to_type(child, builder, handler))
128 .collect::<Result<Vec<_>>>()?;
129 leo_ast::FutureType::new(types, None, true).into()
130 }
131 }
132 TypeKind::Group => leo_ast::Type::Group,
133 TypeKind::Identifier => todo!(),
134 TypeKind::Integer(int_type_kind) => {
135 let int_type = match int_type_kind {
136 IntegerTypeKind::U8 => leo_ast::IntegerType::U8,
137 IntegerTypeKind::U16 => leo_ast::IntegerType::U16,
138 IntegerTypeKind::U32 => leo_ast::IntegerType::U32,
139 IntegerTypeKind::U64 => leo_ast::IntegerType::U64,
140 IntegerTypeKind::U128 => leo_ast::IntegerType::U128,
141 IntegerTypeKind::I8 => leo_ast::IntegerType::I8,
142 IntegerTypeKind::I16 => leo_ast::IntegerType::I16,
143 IntegerTypeKind::I32 => leo_ast::IntegerType::I32,
144 IntegerTypeKind::I64 => leo_ast::IntegerType::I64,
145 IntegerTypeKind::I128 => leo_ast::IntegerType::I128,
146 };
147 leo_ast::Type::Integer(int_type)
148 }
149 TypeKind::Mapping => {
150 todo!()
151 }
152 TypeKind::Optional => {
153 let [inner_type, _q] = &node.children[..] else {
154 panic!("Can't happen");
157 };
158 leo_ast::Type::Optional(leo_ast::OptionalType { inner: Box::new(to_type(inner_type, builder, handler)?) })
159 }
160 TypeKind::Scalar => leo_ast::Type::Scalar,
161 TypeKind::Signature => leo_ast::Type::Signature,
162 TypeKind::String => leo_ast::Type::String,
163 TypeKind::Tuple => {
164 let elements = node
165 .children
166 .iter()
167 .filter(|child| matches!(child.kind, SyntaxKind::Type(..)))
168 .map(|child| to_type(child, builder, handler))
169 .collect::<Result<Vec<_>>>()?;
170 leo_ast::TupleType::new(elements).into()
171 }
172 TypeKind::Vector => {
173 let [_l, type_, _r] = &node.children[..] else {
174 panic!("Can't happen");
177 };
178 let element_type = to_type(type_, builder, handler)?;
179 leo_ast::VectorType { element_type: Box::new(element_type) }.into()
180 }
181 TypeKind::Numeric => leo_ast::Type::Numeric,
182 TypeKind::Unit => leo_ast::Type::Unit,
183 };
184
185 Ok(type_)
186}
187
188fn to_block(node: &SyntaxNode<'_>, builder: &NodeBuilder, handler: &Handler) -> Result<leo_ast::Block> {
189 assert_eq!(node.kind, SyntaxKind::Statement(StatementKind::Block));
190
191 let statements = node
192 .children
193 .iter()
194 .filter(|child| matches!(child.kind, SyntaxKind::Statement(..)))
195 .map(|child| to_statement(child, builder, handler))
196 .collect::<Result<Vec<_>>>()?;
197 Ok(leo_ast::Block { statements, span: node.span, id: builder.next_id() })
198}
199
200pub fn to_statement(node: &SyntaxNode<'_>, builder: &NodeBuilder, handler: &Handler) -> Result<leo_ast::Statement> {
201 let SyntaxKind::Statement(statement_kind) = node.kind else { todo!() };
202
203 let span = node.span;
204 let id = builder.next_id();
205
206 let value = match statement_kind {
207 StatementKind::Assert => {
208 let [_a, _left, expr, _right, _s] = &node.children[..] else {
209 panic!("Can't happen");
210 };
211
212 let expr = to_expression(expr, builder, handler)?;
213 let variant = leo_ast::AssertVariant::Assert(expr);
214
215 leo_ast::AssertStatement { variant, span, id }.into()
216 }
217 StatementKind::AssertEq => {
218 let [_a, _left, e0, _c, e1, _right, _s] = &node.children[..] else {
219 panic!("Can't happen");
220 };
221
222 let e0 = to_expression(e0, builder, handler)?;
223 let e1 = to_expression(e1, builder, handler)?;
224 let variant = leo_ast::AssertVariant::AssertEq(e0, e1);
225
226 leo_ast::AssertStatement { variant, span, id }.into()
227 }
228 StatementKind::AssertNeq => {
229 let [_a, _left, e0, _c, e1, _right, _s] = &node.children[..] else {
230 panic!("Can't happen");
231 };
232
233 let e0 = to_expression(e0, builder, handler)?;
234 let e1 = to_expression(e1, builder, handler)?;
235 let variant = leo_ast::AssertVariant::AssertNeq(e0, e1);
236
237 leo_ast::AssertStatement { variant, span, id }.into()
238 }
239 StatementKind::Assign => {
240 let [lhs, a, rhs, _s] = &node.children[..] else {
241 panic!("Can't happen");
242 };
243
244 let left = to_expression(lhs, builder, handler)?;
245 let right = to_expression(rhs, builder, handler)?;
246 if a.text == "=" {
247 leo_ast::AssignStatement { place: left, value: right, span, id }.into()
249 } else {
250 let op = match a.text {
252 "+=" => leo_ast::BinaryOperation::Add,
253 "-=" => leo_ast::BinaryOperation::Sub,
254 "*=" => leo_ast::BinaryOperation::Mul,
255 "/=" => leo_ast::BinaryOperation::Div,
256 "%=" => leo_ast::BinaryOperation::Rem,
257 "**=" => leo_ast::BinaryOperation::Pow,
258 "<<=" => leo_ast::BinaryOperation::Shl,
259 ">>=" => leo_ast::BinaryOperation::Shr,
260 "&=" => leo_ast::BinaryOperation::BitwiseAnd,
261 "|=" => leo_ast::BinaryOperation::BitwiseOr,
262 "^=" => leo_ast::BinaryOperation::Xor,
263 "&&=" => leo_ast::BinaryOperation::And,
264 "||=" => leo_ast::BinaryOperation::Or,
265 _ => panic!("Can't happen"),
266 };
267
268 let binary_expr = leo_ast::BinaryExpression { left: left.clone(), right, op, span, id };
269
270 leo_ast::AssignStatement { place: left, value: binary_expr.into(), span, id }.into()
271 }
272 }
273 StatementKind::Block => to_block(node, builder, handler)?.into(),
274 StatementKind::Conditional => {
275 match &node.children[..] {
276 [_if, c, block] => {
277 let condition = to_expression(c, builder, handler)?;
279 let then = to_block(block, builder, handler)?;
280 leo_ast::ConditionalStatement { condition, then, otherwise: None, span, id }.into()
281 }
282 [_if, c, block, _else, otherwise] => {
283 let condition = to_expression(c, builder, handler)?;
285 let then = to_block(block, builder, handler)?;
286 let otherwise = to_statement(otherwise, builder, handler)?;
287 leo_ast::ConditionalStatement { condition, then, otherwise: Some(Box::new(otherwise)), span, id }
288 .into()
289 }
290
291 _ => panic!("Can't happen"),
292 }
293 }
294 StatementKind::Const => {
295 let [_const, name, _c, type_, _a, rhs, _s] = &node.children[..] else {
296 panic!("Can't happen");
297 };
298
299 let place = to_identifier(name, builder);
300 let type_ = to_type(type_, builder, handler)?;
301 let value = to_expression(rhs, builder, handler)?;
302
303 leo_ast::ConstDeclaration { place, type_, value, span, id }.into()
304 }
305 StatementKind::Definition => {
306 match &node.children[..] {
307 [_let, name, _c, type_, _assign, e, _s] => {
308 let name = to_identifier(name, builder);
310 let place = leo_ast::DefinitionPlace::Single(name);
311 let value = to_expression(e, builder, handler)?;
312 let type_ = Some(to_type(type_, builder, handler)?);
313 leo_ast::DefinitionStatement { place, type_, value, span, id }.into()
314 }
315 [_let, name, _assign, e, _s] => {
316 let name = to_identifier(name, builder);
318 let place = leo_ast::DefinitionPlace::Single(name);
319 let value = to_expression(e, builder, handler)?;
320 leo_ast::DefinitionStatement { place, type_: None, value, span, id }.into()
321 }
322 children => {
323 let right_paren_index = children.iter().position(|child| child.text == ")").unwrap();
325
326 let names = children[2..right_paren_index].iter()
328 .filter(|child| child.text != ",")
330 .map(|child| to_identifier(child, builder))
331 .collect();
332
333 let type_ = children
335 .iter()
336 .find(|child| matches!(child.kind, SyntaxKind::Type(..)))
337 .map(|child| to_type(child, builder, handler))
338 .transpose()?;
339
340 let expr = &children[children.len() - 2];
341 let value = to_expression(expr, builder, handler)?;
342 let place = leo_ast::DefinitionPlace::Multiple(names);
343 leo_ast::DefinitionStatement { place, type_, value, span, id }.into()
344 }
345 }
346 }
347 StatementKind::Expression => {
348 let expression = to_expression(&node.children[0], builder, handler)?;
349 leo_ast::ExpressionStatement { expression, span, id }.into()
350 }
351 StatementKind::Iteration => {
352 match &node.children[..] {
353 [_f, i, _n, low, _d, hi, block] => {
354 leo_ast::IterationStatement {
356 variable: to_identifier(i, builder),
357 type_: None,
358 start: to_expression(low, builder, handler)?,
359 stop: to_expression(hi, builder, handler)?,
360 inclusive: false,
361 block: to_block(block, builder, handler)?,
362 span,
363 id,
364 }
365 .into()
366 }
367 [_f, i, _c, type_, _n, low, _d, hi, block] => {
368 leo_ast::IterationStatement {
370 variable: to_identifier(i, builder),
371 type_: Some(to_type(type_, builder, handler)?),
372 start: to_expression(low, builder, handler)?,
373 stop: to_expression(hi, builder, handler)?,
374 inclusive: false,
375 block: to_block(block, builder, handler)?,
376 span,
377 id,
378 }
379 .into()
380 }
381 _ => panic!("Can't happen"),
382 }
383 }
384 StatementKind::Return => {
385 match &node.children[..] {
386 [_r, e, _s] => {
387 let expression = to_expression(e, builder, handler)?;
389 leo_ast::ReturnStatement { expression, span, id }.into()
390 }
391 [_r, _s] => {
392 leo_ast::ReturnStatement {
394 expression: leo_ast::UnitExpression { span, id: builder.next_id() }.into(),
395 span,
396 id,
397 }
398 .into()
399 }
400 _ => panic!("Can't happen"),
401 }
402 }
403 };
404
405 Ok(value)
406}
407
408pub fn to_expression(node: &SyntaxNode<'_>, builder: &NodeBuilder, handler: &Handler) -> Result<Expression> {
409 let SyntaxKind::Expression(expression_kind) = node.kind else { panic!("Can't happen") };
410
411 let span = node.span;
412 let id = builder.next_id();
413 let text = || node.text.to_string();
414
415 let value = match expression_kind {
416 ExpressionKind::ArrayAccess => {
417 let [array, _left, index, _right] = &node.children[..] else {
418 panic!("Can't happen");
419 };
420
421 let array = to_expression(array, builder, handler)?;
422 let index = to_expression(index, builder, handler)?;
423
424 leo_ast::ArrayAccess { array, index, span, id }.into()
425 }
426
427 ExpressionKind::Intrinsic => {
428 let name = Symbol::intern(node.children[0].text);
429
430 let mut type_parameters = Vec::new();
431 if let Some(parameter_list) =
432 node.children.iter().find(|child| matches!(child.kind, SyntaxKind::ConstArgumentList))
433 {
434 type_parameters = parameter_list
435 .children
436 .iter()
437 .filter(|child| match child.kind {
438 SyntaxKind::Type(..) => true,
439 SyntaxKind::Expression(..) => {
440 handler.emit_err(ParserError::custom(
441 "Intrinsics may only have type parameters as generic arguments",
442 child.span,
443 ));
444 false
445 }
446 _ => false,
447 })
448 .map(|child| Ok((to_type(child, builder, handler)?, child.span)))
449 .collect::<Result<Vec<_>>>()?;
450 }
451 let arguments = node
452 .children
453 .iter()
454 .filter(|child| matches!(child.kind, SyntaxKind::Expression(..)))
455 .map(|child| to_expression(child, builder, handler))
456 .collect::<Result<Vec<_>>>()?;
457
458 leo_ast::IntrinsicExpression { name, type_parameters, arguments, span, id }.into()
459 }
460
461 ExpressionKind::AssociatedConstant => {
462 leo_ast::IntrinsicExpression { name: sym::_group_gen, type_parameters: vec![], arguments: vec![], span, id }
464 .into()
465 }
466 ExpressionKind::AssociatedFunctionCall => {
467 let mut components = path_to_parts(&node.children[0], builder);
468 let name = components.pop().unwrap();
469 let variant = components.pop().unwrap();
470
471 let mut type_parameters = Vec::new();
472 if let Some(parameter_list) =
473 node.children.iter().find(|child| matches!(child.kind, SyntaxKind::ConstArgumentList))
474 {
475 type_parameters = parameter_list
476 .children
477 .iter()
478 .filter(|child| match child.kind {
479 SyntaxKind::Type(..) => true,
480 SyntaxKind::Expression(..) => {
481 handler.emit_err(ParserError::custom(
482 "Associated function calls may only have type parameters as generic arguments",
483 child.span,
484 ));
485 false
486 }
487 _ => false,
488 })
489 .map(|child| Ok((to_type(child, builder, handler)?, child.span)))
490 .collect::<Result<Vec<_>>>()?;
491 }
492 let arguments = node
493 .children
494 .iter()
495 .filter(|child| matches!(child.kind, SyntaxKind::Expression(..)))
496 .map(|child| to_expression(child, builder, handler))
497 .collect::<Result<Vec<_>>>()?;
498
499 if let Some(converted_name) = Intrinsic::convert_path_symbols(variant.name, name.name) {
500 leo_ast::IntrinsicExpression { name: converted_name, type_parameters, arguments, span, id }.into()
501 } else {
502 handler.emit_err(ParserError::custom(
503 format!("Unknown associated function: {}::{}", variant, name,),
504 span,
505 ));
506 leo_ast::ErrExpression { span, id }.into()
507 }
508 }
509 ExpressionKind::Async => {
510 let [_a, block] = &node.children[..] else {
511 panic!("Can't happen");
512 };
513 leo_ast::AsyncExpression { block: to_block(block, builder, handler)?, span, id }.into()
514 }
515 ExpressionKind::Array => {
516 let elements = node
517 .children
518 .iter()
519 .filter(|child| matches!(child.kind, SyntaxKind::Expression(..)))
520 .map(|child| to_expression(child, builder, handler))
521 .collect::<Result<Vec<_>>>()?;
522 leo_ast::ArrayExpression { elements, span, id }.into()
523 }
524 ExpressionKind::Binary => {
525 let [lhs, op, rhs] = &node.children[..] else {
526 panic!("Can't happen");
527 };
528 let op = match op.text {
533 "==" => leo_ast::BinaryOperation::Eq,
534 "!=" => leo_ast::BinaryOperation::Neq,
535 "<" => leo_ast::BinaryOperation::Lt,
536 "<=" => leo_ast::BinaryOperation::Lte,
537 ">" => leo_ast::BinaryOperation::Gt,
538 ">=" => leo_ast::BinaryOperation::Gte,
539 "+" => leo_ast::BinaryOperation::Add,
540 "-" => leo_ast::BinaryOperation::Sub,
541 "*" => leo_ast::BinaryOperation::Mul,
542 "/" => leo_ast::BinaryOperation::Div,
543 "%" => leo_ast::BinaryOperation::Rem,
544 "||" => leo_ast::BinaryOperation::Or,
545 "&&" => leo_ast::BinaryOperation::And,
546 "|" => leo_ast::BinaryOperation::BitwiseOr,
547 "&" => leo_ast::BinaryOperation::BitwiseAnd,
548 "**" => leo_ast::BinaryOperation::Pow,
549 "<<" => leo_ast::BinaryOperation::Shl,
550 ">>" => leo_ast::BinaryOperation::Shr,
551 "^" => leo_ast::BinaryOperation::Xor,
552 _ => panic!("Can't happen"),
553 };
554 let left = to_expression(lhs, builder, handler)?;
555 let right = to_expression(rhs, builder, handler)?;
556
557 leo_ast::BinaryExpression { left, right, op, span, id }.into()
558 }
559 ExpressionKind::Call => {
560 let name = &node.children[0];
561
562 let arguments = node
563 .children
564 .iter()
565 .filter(|child| matches!(child.kind, SyntaxKind::Expression(..)))
566 .map(|child| to_expression(child, builder, handler))
567 .collect::<Result<Vec<_>>>()?;
568
569 let (function, program) = if let Some((first, second)) = name.text.split_once(".aleo/") {
570 let symbol = Symbol::intern(second);
572 let lo = node.span.lo + first.len() as u32 + ".aleo/".len() as u32;
573 let second_span = Span { lo, hi: lo + second.len() as u32 };
574 let identifier = leo_ast::Identifier { name: symbol, span: second_span, id: builder.next_id() };
575 let function = leo_ast::Path::new(Vec::new(), identifier, false, None, span, builder.next_id());
576 (function, Some(Symbol::intern(first)))
577 } else {
578 let mut components = path_to_parts(name, builder);
580 let identifier = components.pop().unwrap();
581 let function = leo_ast::Path::new(components, identifier, false, None, name.span, builder.next_id());
582 (function, None)
583 };
584
585 let mut const_arguments = Vec::new();
586 if let Some(argument_list) =
587 node.children.iter().find(|child| matches!(child.kind, SyntaxKind::ConstArgumentList))
588 {
589 const_arguments = argument_list
590 .children
591 .iter()
592 .filter(|child| match child.kind {
593 SyntaxKind::Expression(..) => true,
594 SyntaxKind::Type(..) => {
595 handler.emit_err(ParserError::custom(
596 "Function calls may only have constant expressions as generic arguments",
597 child.span,
598 ));
599 false
600 }
601 _ => false,
602 })
603 .map(|child| to_expression(child, builder, handler))
604 .collect::<Result<Vec<_>>>()?;
605 }
606
607 leo_ast::CallExpression { function, const_arguments, arguments, program, span, id }.into()
608 }
609 ExpressionKind::Cast => {
610 let [expression, _as, type_] = &node.children[..] else {
611 panic!("Can't happen");
612 };
613
614 let expression = to_expression(expression, builder, handler)?;
615 let type_ = to_type(type_, builder, handler)?;
616
617 leo_ast::CastExpression { expression, type_, span, id }.into()
618 }
619 ExpressionKind::Path => {
620 let mut identifiers = path_to_parts(&node.children[0], builder);
623 let identifier = identifiers.pop().unwrap();
624 leo_ast::Path::new(identifiers, identifier, false, None, span, id).into()
625 }
626 ExpressionKind::Literal(literal_kind) => match literal_kind {
627 LiteralKind::Address => {
628 let t = text();
629 if !t.contains(".aleo") && t.parse::<Address<TestnetV0>>().is_err() {
630 handler.emit_err(ParserError::invalid_address_lit(&t, span));
633 }
634 leo_ast::Literal::address(t, span, id).into()
635 }
636 LiteralKind::Boolean => match node.text {
637 "true" => leo_ast::Literal::boolean(true, span, id).into(),
638 "false" => leo_ast::Literal::boolean(false, span, id).into(),
639 _ => panic!("Can't happen"),
640 },
641 LiteralKind::Field => leo_ast::Literal::field(text(), span, id).into(),
642 LiteralKind::Group => leo_ast::Literal::group(text(), span, id).into(),
643 LiteralKind::Integer(integer_literal_kind) => {
644 let integer_type = match integer_literal_kind {
645 IntegerLiteralKind::U8 => leo_ast::IntegerType::U8,
646 IntegerLiteralKind::U16 => leo_ast::IntegerType::U16,
647 IntegerLiteralKind::U32 => leo_ast::IntegerType::U32,
648 IntegerLiteralKind::U64 => leo_ast::IntegerType::U64,
649 IntegerLiteralKind::U128 => leo_ast::IntegerType::U128,
650 IntegerLiteralKind::I8 => leo_ast::IntegerType::I8,
651 IntegerLiteralKind::I16 => leo_ast::IntegerType::I16,
652 IntegerLiteralKind::I32 => leo_ast::IntegerType::I32,
653 IntegerLiteralKind::I64 => leo_ast::IntegerType::I64,
654 IntegerLiteralKind::I128 => leo_ast::IntegerType::I128,
655 };
656 leo_ast::Literal::integer(integer_type, text(), span, id).into()
657 }
658 LiteralKind::None => leo_ast::Literal::none(span, id).into(),
659 LiteralKind::Scalar => leo_ast::Literal::scalar(text(), span, id).into(),
660 LiteralKind::Unsuffixed => leo_ast::Literal::unsuffixed(text(), span, id).into(),
661 LiteralKind::String => leo_ast::Literal::string(text(), span, id).into(),
662 },
663 ExpressionKind::Locator => {
664 let text = node.children[0].text;
665
666 if let Some((program_part, name_part)) = text.split_once(".aleo/") {
668 let program_name_symbol = Symbol::intern(program_part);
670 let program_name_span = Span { lo: node.span.lo, hi: node.span.lo + program_part.len() as u32 };
671 let program_name =
672 leo_ast::Identifier { name: program_name_symbol, span: program_name_span, id: builder.next_id() };
673
674 let network_start = node.span.lo + program_part.len() as u32 + 1; let network_span = Span {
677 lo: network_start,
678 hi: network_start + 4, };
680 let network =
681 leo_ast::Identifier { name: Symbol::intern("aleo"), span: network_span, id: builder.next_id() };
682
683 let program_id = leo_ast::ProgramId { name: program_name, network };
685
686 let name_symbol = Symbol::intern(name_part);
688
689 leo_ast::LocatorExpression { program: program_id, name: name_symbol, span, id }.into()
690 } else {
691 handler.emit_err(ParserError::custom("Invalid locator format", span));
693 leo_ast::ErrExpression { span, id }.into()
694 }
695 }
696 ExpressionKind::MemberAccess => {
697 let [struct_, _dot, name] = &node.children[..] else {
698 panic!("Can't happen.");
699 };
700 let inner = to_expression(struct_, builder, handler)?;
701 let name = to_identifier(name, builder);
702
703 leo_ast::MemberAccess { inner, name, span, id }.into()
704 }
705 ExpressionKind::MethodCall => {
706 let [expr, _dot, name, ..] = &node.children[..] else {
707 panic!("Can't happen");
708 };
709
710 let name = to_identifier(name, builder);
711 let receiver = to_expression(expr, builder, handler)?;
712
713 let mut args = node.children[3..]
714 .iter()
715 .filter(|child| matches!(child.kind, SyntaxKind::Expression(..)))
716 .map(|child| to_expression(child, builder, handler))
717 .collect::<Result<Vec<_>>>()?;
718
719 if let (true, Some(op)) = (args.is_empty(), leo_ast::UnaryOperation::from_symbol(name.name)) {
720 leo_ast::UnaryExpression { span, op, receiver, id }.into()
722 } else if let (1, Some(op)) = (args.len(), leo_ast::BinaryOperation::from_symbol(name.name)) {
723 leo_ast::BinaryExpression { span, op, left: receiver, right: args.pop().unwrap(), id }.into()
725 } else if let (2, Some(name @ sym::_signature_verify)) =
726 (args.len(), leo_ast::Intrinsic::convert_path_symbols(sym::signature, name.name))
727 {
728 leo_ast::IntrinsicExpression {
729 name,
730 type_parameters: Vec::new(),
731 arguments: std::iter::once(receiver).chain(args).collect(),
732 span,
733 id,
734 }
735 .into()
736 } else if let (0, Some(name @ sym::_future_await)) =
737 (args.len(), leo_ast::Intrinsic::convert_path_symbols(sym::Future, name.name))
738 {
739 leo_ast::IntrinsicExpression {
740 name,
741 type_parameters: Vec::new(),
742 arguments: vec![receiver],
743 span,
744 id: builder.next_id(),
745 }
746 .into()
747 } else if let (0, Some(name @ sym::_optional_unwrap)) =
748 (args.len(), leo_ast::Intrinsic::convert_path_symbols(sym::Optional, name.name))
749 {
750 leo_ast::IntrinsicExpression {
751 name,
752 type_parameters: Vec::new(),
753 arguments: vec![receiver],
754 span,
755 id: builder.next_id(),
756 }
757 .into()
758 } else if let (1, Some(name @ sym::_optional_unwrap_or)) =
759 (args.len(), leo_ast::Intrinsic::convert_path_symbols(sym::Optional, name.name))
760 {
761 leo_ast::IntrinsicExpression {
762 name,
763 type_parameters: Vec::new(),
764 arguments: std::iter::once(receiver).chain(args).collect(),
765 span,
766 id: builder.next_id(),
767 }
768 .into()
769 } else if let (1, sym::get) = (args.len(), name.name) {
770 leo_ast::IntrinsicExpression {
771 name: Symbol::intern("__unresolved_get"),
772 type_parameters: Vec::new(),
773 arguments: std::iter::once(receiver).chain(args).collect(),
774 span,
775 id: builder.next_id(),
776 }
777 .into()
778 } else if let (2, sym::set) = (args.len(), name.name) {
779 leo_ast::IntrinsicExpression {
780 name: Symbol::intern("__unresolved_set"),
781 type_parameters: Vec::new(),
782 arguments: std::iter::once(receiver).chain(args).collect(),
783 span,
784 id,
785 }
786 .into()
787 } else if let (1, Some(name @ sym::_vector_push)) =
788 (args.len(), leo_ast::Intrinsic::convert_path_symbols(sym::Vector, name.name))
789 {
790 leo_ast::IntrinsicExpression {
791 name,
792 type_parameters: Vec::new(),
793 arguments: std::iter::once(receiver).chain(args).collect(),
794 span,
795 id: builder.next_id(),
796 }
797 .into()
798 } else if let (0, Some(name @ sym::_vector_len)) =
799 (args.len(), leo_ast::Intrinsic::convert_path_symbols(sym::Vector, name.name))
800 {
801 leo_ast::IntrinsicExpression {
802 name,
803 type_parameters: Vec::new(),
804 arguments: vec![receiver],
805 span,
806 id: builder.next_id(),
807 }
808 .into()
809 } else if let (0, Some(name @ sym::_vector_pop)) =
810 (args.len(), leo_ast::Intrinsic::convert_path_symbols(sym::Vector, name.name))
811 {
812 leo_ast::IntrinsicExpression {
813 name,
814 type_parameters: Vec::new(),
815 arguments: vec![receiver],
816 span,
817 id: builder.next_id(),
818 }
819 .into()
820 } else if let (0, Some(name @ sym::_vector_clear)) =
821 (args.len(), leo_ast::Intrinsic::convert_path_symbols(sym::Vector, name.name))
822 {
823 leo_ast::IntrinsicExpression {
824 name,
825 type_parameters: Vec::new(),
826 arguments: vec![receiver],
827 span,
828 id: builder.next_id(),
829 }
830 .into()
831 } else if let (1, Some(name @ sym::_vector_swap_remove)) =
832 (args.len(), leo_ast::Intrinsic::convert_path_symbols(sym::Vector, name.name))
833 {
834 leo_ast::IntrinsicExpression {
835 name,
836 type_parameters: Vec::new(),
837 arguments: std::iter::once(receiver).chain(args).collect(),
838 span,
839 id: builder.next_id(),
840 }
841 .into()
842 } else {
843 match (args.len(), leo_ast::Intrinsic::convert_path_symbols(sym::Mapping, name.name)) {
845 (2, Some(name @ sym::_mapping_get_or_use))
846 | (1, Some(name @ sym::_mapping_remove))
847 | (1, Some(name @ sym::_mapping_contains)) => {
848 leo_ast::IntrinsicExpression {
850 name,
851 type_parameters: Vec::new(),
852 arguments: std::iter::once(receiver).chain(args).collect(),
853 span,
854 id: builder.next_id(),
855 }
856 .into()
857 }
858 _ => {
859 handler.emit_err(ParserError::invalid_method_call(receiver, name, args.len(), span));
861 leo_ast::ErrExpression { span, id: builder.next_id() }.into()
862 }
863 }
864 }
865 }
866 ExpressionKind::Parenthesized => {
867 let [_left, expr, _right] = &node.children[..] else {
868 panic!("Can't happen");
869 };
870 to_expression(expr, builder, handler)?
871 }
872 ExpressionKind::Repeat => {
873 let [_left, expr, _s, count, _right] = &node.children[..] else {
874 panic!("Can't happen");
875 };
876 let expr = to_expression(expr, builder, handler)?;
877 let count = to_expression(count, builder, handler)?;
878 leo_ast::RepeatExpression { expr, count, span, id }.into()
879 }
880 ExpressionKind::SpecialAccess => {
881 let [qualifier, _dot, name] = &node.children[..] else {
882 panic!("Can't happen");
883 };
884
885 let name = match (qualifier.text, name.text) {
886 ("self", "address") => Some(sym::_self_address),
887 ("self", "caller") => Some(sym::_self_caller),
888 ("self", "checksum") => Some(sym::_self_checksum),
889 ("self", "edition") => Some(sym::_self_edition),
890 ("self", "id") => Some(sym::_self_id),
891 ("self", "program_owner") => Some(sym::_self_program_owner),
892 ("self", "signer") => Some(sym::_self_signer),
893 ("block", "height") => Some(sym::_block_height),
894 ("block", "timestamp") => Some(sym::_block_timestamp),
895 ("network", "id") => Some(sym::_network_id),
896 _ => {
897 handler.emit_err(ParserError::custom("Unsupported special access", node.span));
898 None
899 }
900 };
901
902 if let Some(name) = name {
903 leo_ast::IntrinsicExpression { name, type_parameters: vec![], arguments: vec![], span, id }.into()
904 } else {
905 leo_ast::ErrExpression { span, id: builder.next_id() }.into()
906 }
907 }
908
909 ExpressionKind::Struct => {
910 let name = &node.children[0];
911 let mut members = Vec::new();
912 for initializer in node.children.iter().filter(|node| node.kind == SyntaxKind::StructMemberInitializer) {
913 let (init_name, expression) = match &initializer.children[..] {
914 [init_name] => (init_name, None),
915 [init_name, _c, expr] => (init_name, Some(to_expression(expr, builder, handler)?)),
916 _ => panic!("Can't happen"),
917 };
918 let init_name = to_identifier(init_name, builder);
919
920 members.push(leo_ast::StructVariableInitializer {
921 identifier: init_name,
922 expression,
923 span: initializer.span,
924 id: builder.next_id(),
925 });
926 }
927
928 let mut const_arguments = Vec::new();
929 let maybe_const_params = &node.children[1];
930 if maybe_const_params.kind == SyntaxKind::ConstArgumentList {
931 for argument in &maybe_const_params.children {
932 match argument.kind {
933 SyntaxKind::Type(..) => {
934 handler.emit_err(ParserError::custom(
935 "Struct expressions may only have constant expressions as generic arguments",
936 argument.span,
937 ));
938 }
939 SyntaxKind::Expression(..) => {
940 let expr = to_expression(argument, builder, handler)?;
941 const_arguments.push(expr);
942 }
943 _ => {}
944 }
945 }
946 }
947
948 let mut identifiers = path_to_parts(name, builder);
949 let identifier = identifiers.pop().unwrap();
950 let path = leo_ast::Path::new(identifiers, identifier, false, None, name.span, builder.next_id());
951
952 leo_ast::StructExpression { path, const_arguments, members, span, id }.into()
953 }
954 ExpressionKind::Ternary => {
955 let [cond, _q, if_, _c, then] = &node.children[..] else {
956 panic!("Can't happen");
957 };
958 let condition = to_expression(cond, builder, handler)?;
959 let if_true = to_expression(if_, builder, handler)?;
960 let if_false = to_expression(then, builder, handler)?;
961 leo_ast::TernaryExpression { condition, if_true, if_false, span, id }.into()
962 }
963 ExpressionKind::Tuple => {
964 let elements = node
965 .children
966 .iter()
967 .filter(|expr| matches!(expr.kind, SyntaxKind::Expression(..)))
968 .map(|expr| to_expression(expr, builder, handler))
969 .collect::<Result<Vec<_>>>()?;
970 leo_ast::TupleExpression { elements, span, id }.into()
971 }
972 ExpressionKind::TupleAccess => {
973 let [expr, _dot, integer] = &node.children[..] else {
974 panic!("Can't happen");
975 };
976
977 let tuple = to_expression(expr, builder, handler)?;
978 let integer_text = integer.text.replace("_", "");
979 let value: usize = integer_text.parse().expect("Integer should parse.");
980 let index = value.into();
981
982 leo_ast::TupleAccess { tuple, index, span, id }.into()
983 }
984 ExpressionKind::Unary => {
985 let [op, operand] = &node.children[..] else {
986 panic!("Can't happen");
987 };
988 let mut operand_expression = to_expression(operand, builder, handler)?;
989 let op_variant = match op.text {
990 "!" => leo_ast::UnaryOperation::Not,
991 "-" => leo_ast::UnaryOperation::Negate,
992 _ => panic!("Can't happen"),
993 };
994 if op_variant == leo_ast::UnaryOperation::Negate {
995 use leo_ast::LiteralVariant::*;
996 if let Expression::Literal(leo_ast::Literal {
997 variant: Integer(_, string) | Field(string) | Group(string) | Scalar(string),
998 span,
999 ..
1000 }) = &mut operand_expression
1001 && !string.starts_with('-')
1002 {
1003 string.insert(0, '-');
1006 *span = op.span + operand.span;
1007 return Ok(operand_expression);
1008 }
1009 }
1010 leo_ast::UnaryExpression { receiver: operand_expression, op: op_variant, span, id }.into()
1011 }
1012 ExpressionKind::Unit => leo_ast::UnitExpression { span, id }.into(),
1013 };
1014
1015 Ok(value)
1016}
1017
1018fn to_const_parameters(
1019 node: &SyntaxNode<'_>,
1020 builder: &NodeBuilder,
1021 handler: &Handler,
1022) -> Result<Vec<leo_ast::ConstParameter>> {
1023 assert_eq!(node.kind, SyntaxKind::ConstParameterList);
1024
1025 node.children
1026 .iter()
1027 .filter(|child| matches!(child.kind, SyntaxKind::ConstParameter))
1028 .map(|child| {
1029 let [id, _c, type_] = &child.children[..] else {
1030 panic!("Can't happen");
1031 };
1032
1033 Ok(leo_ast::ConstParameter {
1034 identifier: to_identifier(id, builder),
1035 type_: to_type(type_, builder, handler)?,
1036 span: child.span,
1037 id: builder.next_id(),
1038 })
1039 })
1040 .collect::<Result<Vec<_>>>()
1041}
1042
1043fn to_annotation(node: &SyntaxNode<'_>, builder: &NodeBuilder) -> Result<leo_ast::Annotation> {
1044 assert_eq!(node.kind, SyntaxKind::Annotation);
1045 let name = to_identifier(&node.children[1], builder);
1046
1047 let mut map = IndexMap::new();
1048 node.children.get(2).inspect(|list| {
1049 for member in list.children.iter() {
1050 if member.kind != SyntaxKind::AnnotationMember {
1051 continue;
1052 }
1053
1054 let [key, _assign, value] = &member.children[..] else {
1055 panic!("Can't happen");
1056 };
1057 let key = Symbol::intern(key.text);
1058 let value = value.text[1..value.text.len() - 1].to_string();
1060 map.insert(key, value);
1061 }
1062 });
1063 Ok(leo_ast::Annotation { identifier: name, map, span: node.span, id: builder.next_id() })
1064}
1065
1066fn to_function(node: &SyntaxNode<'_>, builder: &NodeBuilder, handler: &Handler) -> Result<leo_ast::Function> {
1067 assert_eq!(node.kind, SyntaxKind::Function);
1068
1069 let annotations = node
1070 .children
1071 .iter()
1072 .filter(|child| matches!(child.kind, SyntaxKind::Annotation))
1073 .map(|child| to_annotation(child, builder))
1074 .collect::<Result<Vec<_>>>()?;
1075 let async_index = annotations.len();
1076 let is_async = node.children[async_index].text == "async";
1077
1078 let function_variant_index = if is_async { async_index + 1 } else { async_index };
1079
1080 let variant = match (is_async, node.children[function_variant_index].text) {
1083 (true, "function") => leo_ast::Variant::AsyncFunction,
1084 (false, "function") => leo_ast::Variant::Function,
1085 (_, "inline") => leo_ast::Variant::Inline,
1086 (_, "script") => leo_ast::Variant::Script,
1087 (true, "transition") => leo_ast::Variant::AsyncTransition,
1088 (false, "transition") => leo_ast::Variant::Transition,
1089 _ => panic!("Can't happen"),
1090 };
1091
1092 let name = &node.children[function_variant_index + 1];
1093 let id = to_identifier(name, builder);
1094
1095 let mut const_parameters = Vec::new();
1096 if let Some(const_param_list) =
1097 node.children.iter().find(|child| matches!(child.kind, SyntaxKind::ConstParameterList))
1098 {
1099 const_parameters = to_const_parameters(const_param_list, builder, handler)?;
1100 }
1101
1102 let parameter_list = node.children.iter().find(|child| matches!(child.kind, SyntaxKind::ParameterList)).unwrap();
1103 let input = parameter_list
1104 .children
1105 .iter()
1106 .filter(|child| matches!(child.kind, SyntaxKind::Parameter))
1107 .map(|child| {
1108 let mode = to_mode(&child.children[0]);
1109 let index = if mode == leo_ast::Mode::None { 0 } else { 1 };
1110 let [name, _c, type_] = &child.children[index..] else {
1111 panic!("Can't happen");
1112 };
1113 Ok(leo_ast::Input {
1114 identifier: to_identifier(name, builder),
1115 mode,
1116 type_: to_type(type_, builder, handler)?,
1117 span: child.span,
1118 id: builder.next_id(),
1119 })
1120 })
1121 .collect::<Result<Vec<_>>>()?;
1122
1123 let [.., maybe_outputs, block] = &node.children[..] else {
1124 panic!("Can't happen");
1125 };
1126 let block = to_block(block, builder, handler)?;
1127
1128 let to_output = |node: &SyntaxNode<'_>| -> Result<leo_ast::Output> {
1129 let mode = to_mode(&node.children[0]);
1130 let type_ = node.children.last().unwrap();
1131
1132 Ok(leo_ast::Output { mode, type_: to_type(type_, builder, handler)?, span: node.span, id: builder.next_id() })
1133 };
1134
1135 let output = match maybe_outputs.kind {
1136 SyntaxKind::FunctionOutput => {
1137 let output = to_output(maybe_outputs)?;
1138 vec![output]
1139 }
1140 SyntaxKind::FunctionOutputs => maybe_outputs
1141 .children
1142 .iter()
1143 .filter(|child| matches!(child.kind, SyntaxKind::FunctionOutput))
1144 .map(|child| to_output(child))
1145 .collect::<Result<Vec<_>>>()?,
1146 _ => Vec::new(),
1147 };
1148
1149 Ok(leo_ast::Function::new(
1150 annotations,
1151 variant,
1152 id,
1153 const_parameters,
1154 input,
1155 output,
1156 block,
1157 node.span,
1158 builder.next_id(),
1159 ))
1160}
1161
1162fn to_composite(node: &SyntaxNode<'_>, builder: &NodeBuilder, handler: &Handler) -> Result<leo_ast::Composite> {
1163 assert_eq!(node.kind, SyntaxKind::StructDeclaration);
1164
1165 let [struct_or_record, i, .., members] = &node.children[..] else {
1166 panic!("Can't happen");
1167 };
1168
1169 let members = members
1170 .children
1171 .iter()
1172 .filter(|child| matches!(child.kind, SyntaxKind::StructMemberDeclaration))
1173 .map(|child| {
1174 let (mode, ident, type_) = match &child.children[..] {
1175 [ident, _c, type_] => (leo_ast::Mode::None, ident, type_),
1176 [privacy, ident, _c, type_] => (to_mode(privacy), ident, type_),
1177 _ => panic!("Can't happen"),
1178 };
1179
1180 Ok(leo_ast::Member {
1181 mode,
1182 identifier: to_identifier(ident, builder),
1183 type_: to_type(type_, builder, handler)?,
1184 span: child.span,
1185 id: builder.next_id(),
1186 })
1187 })
1188 .collect::<Result<Vec<_>>>()?;
1189
1190 let mut const_parameters = Vec::new();
1191 if let Some(const_param_list) =
1192 node.children.iter().find(|child| matches!(child.kind, SyntaxKind::ConstParameterList))
1193 {
1194 const_parameters = to_const_parameters(const_param_list, builder, handler)?;
1195 }
1196
1197 Ok(leo_ast::Composite {
1198 identifier: to_identifier(i, builder),
1199 const_parameters,
1200 members,
1201 external: None,
1202 is_record: struct_or_record.text == "record",
1203 span: node.span,
1204 id: builder.next_id(),
1205 })
1206}
1207
1208fn to_global_const(
1209 node: &SyntaxNode<'_>,
1210 builder: &NodeBuilder,
1211 handler: &Handler,
1212) -> Result<leo_ast::ConstDeclaration> {
1213 assert_eq!(node.kind, SyntaxKind::GlobalConst);
1214
1215 let [_l, ident, _colon, type_, _a, expr, _s] = &node.children[..] else {
1216 panic!("Can't happen");
1217 };
1218
1219 Ok(leo_ast::ConstDeclaration {
1220 place: to_identifier(ident, builder),
1221 type_: to_type(type_, builder, handler)?,
1222 value: to_expression(expr, builder, handler)?,
1223 span: node.span,
1224 id: builder.next_id(),
1225 })
1226}
1227
1228fn to_constructor(node: &SyntaxNode<'_>, builder: &NodeBuilder, handler: &Handler) -> Result<leo_ast::Constructor> {
1229 assert_eq!(node.kind, SyntaxKind::Constructor);
1230 let annotations = node
1231 .children
1232 .iter()
1233 .filter(|child| matches!(child.kind, SyntaxKind::Annotation))
1234 .map(|child| to_annotation(child, builder))
1235 .collect::<Result<Vec<_>>>()?;
1236 let block = to_block(node.children.last().unwrap(), builder, handler)?;
1237
1238 Ok(leo_ast::Constructor { annotations, block, span: node.span, id: builder.next_id() })
1239}
1240
1241fn to_mapping(node: &SyntaxNode<'_>, builder: &NodeBuilder, handler: &Handler) -> Result<leo_ast::Mapping> {
1242 assert_eq!(node.kind, SyntaxKind::Mapping);
1243
1244 let [_mapping, name, _colon, key_type, _arrow, value_type, _s] = &node.children[..] else {
1245 panic!("Can't happen");
1246 };
1247
1248 Ok(leo_ast::Mapping {
1249 identifier: to_identifier(name, builder),
1250 key_type: to_type(key_type, builder, handler)?,
1251 value_type: to_type(value_type, builder, handler)?,
1252 span: node.span,
1253 id: builder.next_id(),
1254 })
1255}
1256
1257fn to_storage_variable(
1258 node: &SyntaxNode<'_>,
1259 builder: &NodeBuilder,
1260 handler: &Handler,
1261) -> Result<leo_ast::StorageVariable> {
1262 assert_eq!(node.kind, SyntaxKind::Storage);
1263
1264 let [_storage, name, _colon, type_, _s] = &node.children[..] else {
1265 panic!("Can't happen");
1266 };
1267
1268 Ok(leo_ast::StorageVariable {
1269 identifier: to_identifier(name, builder),
1270 type_: to_type(type_, builder, handler)?,
1271 span: node.span,
1272 id: builder.next_id(),
1273 })
1274}
1275
1276pub fn to_module(
1277 node: &SyntaxNode<'_>,
1278 builder: &NodeBuilder,
1279 program_name: Symbol,
1280 path: Vec<Symbol>,
1281 handler: &Handler,
1282) -> Result<leo_ast::Module> {
1283 assert_eq!(node.kind, SyntaxKind::ModuleContents);
1284
1285 let mut functions = node
1286 .children
1287 .iter()
1288 .filter(|child| matches!(child.kind, SyntaxKind::Function))
1289 .map(|child| {
1290 let function = to_function(child, builder, handler)?;
1291 Ok((function.identifier.name, function))
1292 })
1293 .collect::<Result<Vec<_>>>()?;
1294 functions.sort_by_key(|func| if func.1.variant.is_transition() { 0u8 } else { 1u8 });
1297
1298 let structs = node
1299 .children
1300 .iter()
1301 .filter(|child| matches!(child.kind, SyntaxKind::StructDeclaration))
1302 .map(|child| {
1303 let composite = to_composite(child, builder, handler)?;
1304 Ok((composite.identifier.name, composite))
1305 })
1306 .collect::<Result<Vec<_>>>()?;
1307
1308 let consts = node
1309 .children
1310 .iter()
1311 .filter(|child| matches!(child.kind, SyntaxKind::GlobalConst))
1312 .map(|child| {
1313 let global_const = to_global_const(child, builder, handler)?;
1314 Ok((global_const.place.name, global_const))
1315 })
1316 .collect::<Result<Vec<_>>>()?;
1317
1318 Ok(leo_ast::Module { program_name, path, consts, structs, functions })
1319}
1320
1321pub fn to_main(node: &SyntaxNode<'_>, builder: &NodeBuilder, handler: &Handler) -> Result<leo_ast::Program> {
1322 assert_eq!(node.kind, SyntaxKind::MainContents);
1323
1324 let imports = node
1325 .children
1326 .iter()
1327 .filter(|child| matches!(child.kind, SyntaxKind::Import))
1328 .map(|child| {
1329 let name = Symbol::intern(child.children[1].text.strip_suffix(".aleo").unwrap());
1330 (name, (leo_ast::Program::default(), child.span))
1331 })
1332 .collect::<IndexMap<_, _>>();
1333
1334 let program_node = node.children.last().unwrap();
1335
1336 let mut functions = program_node
1337 .children
1338 .iter()
1339 .filter(|child| matches!(child.kind, SyntaxKind::Function))
1340 .map(|child| {
1341 let function = to_function(child, builder, handler)?;
1342 Ok((function.identifier.name, function))
1343 })
1344 .collect::<Result<Vec<_>>>()?;
1345 functions.sort_by_key(|func| if func.1.variant.is_transition() { 0u8 } else { 1u8 });
1347
1348 let structs = program_node
1349 .children
1350 .iter()
1351 .filter(|child| matches!(child.kind, SyntaxKind::StructDeclaration))
1352 .map(|child| {
1353 let composite = to_composite(child, builder, handler)?;
1354 Ok((composite.identifier.name, composite))
1355 })
1356 .collect::<Result<Vec<_>>>()?;
1357
1358 let consts = program_node
1359 .children
1360 .iter()
1361 .filter(|child| matches!(child.kind, SyntaxKind::GlobalConst))
1362 .map(|child| {
1363 let global_const = to_global_const(child, builder, handler)?;
1364 Ok((global_const.place.name, global_const))
1365 })
1366 .collect::<Result<Vec<_>>>()?;
1367
1368 let mappings = program_node
1369 .children
1370 .iter()
1371 .filter(|child| matches!(child.kind, SyntaxKind::Mapping))
1372 .map(|child| {
1373 let mapping = to_mapping(child, builder, handler)?;
1374 Ok((mapping.identifier.name, mapping))
1375 })
1376 .collect::<Result<Vec<_>>>()?;
1377
1378 let storage_variables = program_node
1379 .children
1380 .iter()
1381 .filter(|child| matches!(child.kind, SyntaxKind::Storage))
1382 .map(|child| {
1383 let storage_variable = to_storage_variable(child, builder, handler)?;
1384 Ok((storage_variable.identifier.name, storage_variable))
1385 })
1386 .collect::<Result<Vec<_>>>()?;
1387
1388 let mut constructors = program_node
1392 .children
1393 .iter()
1394 .filter(|child| matches!(child.kind, SyntaxKind::Constructor))
1395 .map(|child| to_constructor(child, builder, handler))
1396 .collect::<Result<Vec<_>>>()?;
1397
1398 if let Some(extra) = constructors.get(1) {
1399 return Err(TypeCheckerError::custom("A program can only have one constructor.", extra.span).into());
1400 }
1401
1402 let program_id_node = &program_node.children[1];
1403 let program_name_text = program_id_node.text.strip_suffix(".aleo").unwrap();
1404 let program_name_symbol = Symbol::intern(program_name_text);
1405 let hi = program_id_node.span.lo + program_name_text.len() as u32;
1406 let program_id = leo_ast::ProgramId {
1407 name: leo_ast::Identifier {
1408 name: program_name_symbol,
1409 span: Span { lo: program_id_node.span.lo, hi },
1410 id: builder.next_id(),
1411 },
1412 network: leo_ast::Identifier { name: sym::aleo, span: Span { lo: hi + 1, hi: hi + 5 }, id: builder.next_id() },
1413 };
1414 let program_scope = leo_ast::ProgramScope {
1415 program_id,
1416 consts,
1417 structs,
1418 mappings,
1419 storage_variables,
1420 functions,
1421 constructor: constructors.pop(),
1422 span: node.span,
1423 };
1424 Ok(leo_ast::Program {
1425 modules: Default::default(),
1426 imports,
1427 stubs: Default::default(),
1428 program_scopes: std::iter::once((program_name_symbol, program_scope)).collect(),
1429 })
1430}