1use itertools::Itertools as _;
31use snarkvm::prelude::{Address, Signature, TestnetV0};
32
33use leo_ast::{NetworkName, NodeBuilder, NodeID};
34use leo_errors::{Handler, ParserError, ParserWarning, Result};
35use leo_parser_rowan::{SyntaxElement, SyntaxKind, SyntaxKind::*, SyntaxNode, SyntaxToken, TextRange};
36use leo_span::{
37 Span,
38 Symbol,
39 source_map::{FileName, SourceFile},
40 sym,
41};
42
43type ConstArgList = (Vec<(leo_ast::Type, Span)>, Vec<leo_ast::Expression>);
45
46type AnnotatedTypes = Vec<(leo_ast::Mode, leo_ast::Type, Span)>;
48
49type Parents = Vec<(Span, leo_ast::Type)>;
51
52struct ConversionContext<'a> {
58 handler: &'a Handler,
59 builder: &'a NodeBuilder,
60 start_pos: u32,
62 suppress_cascade: bool,
68}
69
70impl<'a> ConversionContext<'a> {
71 fn new(handler: &'a Handler, builder: &'a NodeBuilder, start_pos: u32, suppress_cascade: bool) -> Self {
73 Self { handler, builder, start_pos, suppress_cascade }
74 }
75
76 fn emit_unexpected_str(&self, expected: &str, found: impl std::fmt::Display, span: Span) {
78 if !self.suppress_cascade {
79 self.handler.emit_err(ParserError::unexpected_str(expected, found, span));
80 }
81 }
82
83 fn to_span(&self, node: &SyntaxNode) -> Span {
89 let range = node.text_range();
90 Span::new(u32::from(range.start()) + self.start_pos, u32::from(range.end()) + self.start_pos)
91 }
92
93 fn token_span(&self, token: &SyntaxToken) -> Span {
95 let range = token.text_range();
96 Span::new(u32::from(range.start()) + self.start_pos, u32::from(range.end()) + self.start_pos)
97 }
98
99 fn non_trivia_span(&self, node: &SyntaxNode) -> Span {
102 let start = first_non_trivia_token(node).map(|t| t.text_range().start()).unwrap_or(node.text_range().start());
103 let end = node.text_range().end();
104 Span::new(u32::from(start) + self.start_pos, u32::from(end) + self.start_pos)
105 }
106
107 fn trimmed_span(&self, node: &SyntaxNode) -> Span {
111 let start = first_non_trivia_token(node).map(|t| t.text_range().start()).unwrap_or(node.text_range().start());
112 let end = last_non_trivia_token(node).map(|t| t.text_range().end()).unwrap_or(node.text_range().end());
113 Span::new(u32::from(start) + self.start_pos, u32::from(end) + self.start_pos)
114 }
115
116 fn content_span(&self, node: &SyntaxNode) -> Span {
120 let mut first = node.text_range().start();
121 let mut last = node.text_range().end();
122 let mut found_first = false;
123 for elem in node.descendants_with_tokens() {
124 if let Some(t) = elem.as_token()
125 && !t.kind().is_trivia()
126 {
127 if !found_first {
128 first = t.text_range().start();
129 found_first = true;
130 }
131 last = t.text_range().end();
132 }
133 }
134 Span::new(u32::from(first) + self.start_pos, u32::from(last) + self.start_pos)
135 }
136
137 fn span_including_annotations(&self, node: &SyntaxNode, span: Span) -> Span {
139 children(node)
140 .find(|n| n.kind() == ANNOTATION)
141 .map(|ann| Span::new(self.trimmed_span(&ann).lo, span.hi))
142 .unwrap_or(span)
143 }
144
145 fn to_identifier(&self, token: &SyntaxToken) -> leo_ast::Identifier {
147 debug_assert_eq!(token.kind(), IDENT);
148 leo_ast::Identifier {
149 name: Symbol::intern(token.text()),
150 span: self.token_span(token),
151 id: self.builder.next_id(),
152 }
153 }
154
155 fn error_identifier(&self, span: Span) -> leo_ast::Identifier {
157 leo_ast::Identifier { name: Symbol::intern("_error"), span, id: self.builder.next_id() }
158 }
159
160 fn error_expression(&self, span: Span) -> leo_ast::Expression {
162 leo_ast::ErrExpression { span, id: self.builder.next_id() }.into()
163 }
164
165 fn intrinsic_expression(
167 &self,
168 name: Symbol,
169 arguments: Vec<leo_ast::Expression>,
170 span: Span,
171 ) -> leo_ast::Expression {
172 leo_ast::IntrinsicExpression {
173 name,
174 type_parameters: Vec::new(),
175 input_types: Vec::new(),
176 return_types: Vec::new(),
177 arguments,
178 span,
179 id: self.builder.next_id(),
180 }
181 .into()
182 }
183
184 fn error_block(&self, span: Span) -> leo_ast::Block {
186 leo_ast::Block { statements: Vec::new(), span, id: self.builder.next_id() }
187 }
188
189 fn validate_hexbin_literal(&self, text: &str, suffix_len: u32, span: Span) {
192 if text.starts_with("0x") || text.starts_with("0o") || text.starts_with("0b") {
193 self.handler.emit_err(ParserError::hexbin_literal_nonintegers(Span::new(span.lo, span.hi - suffix_len)));
194 }
195 }
196
197 fn require_ident(&self, node: &SyntaxNode, label: &str) -> leo_ast::Identifier {
199 let span = self.to_span(node);
200 match tokens(node).find(|t| t.kind() == IDENT) {
201 Some(token) => self.to_identifier(&token),
202 None => {
203 self.emit_unexpected_str(label, node.text(), span);
204 self.error_identifier(span)
205 }
206 }
207 }
208
209 fn require_type(&self, node: &SyntaxNode, label: &str) -> Result<leo_ast::Type> {
211 match children(node).find(|n| n.kind().is_type()) {
212 Some(type_node) => self.to_type(&type_node),
213 None => {
214 self.emit_unexpected_str(label, node.text(), self.to_span(node));
215 Ok(leo_ast::Type::Err)
216 }
217 }
218 }
219
220 fn require_expression(&self, node: &SyntaxNode, label: &str) -> Result<leo_ast::Expression> {
222 match children(node).find(|n| n.kind().is_expression()) {
223 Some(expr_node) => self.to_expression(&expr_node),
224 None => {
225 let span = self.to_span(node);
226 self.emit_unexpected_str(label, node.text(), span);
227 Ok(self.error_expression(span))
228 }
229 }
230 }
231
232 fn validate_identifier(&self, ident: &leo_ast::Identifier) {
234 const MAX_IDENTIFIER_LEN: usize = 31;
235 let text = ident.name.to_string();
236 if text.len() > MAX_IDENTIFIER_LEN {
237 self.handler.emit_err(ParserError::identifier_too_long(&text, text.len(), MAX_IDENTIFIER_LEN, ident.span));
238 }
239 if text.contains("__") {
240 self.handler.emit_err(ParserError::identifier_cannot_contain_double_underscore(&text, ident.span));
241 }
242 }
243
244 fn validate_definition_identifier(&self, ident: &leo_ast::Identifier) {
248 if ident.name == Symbol::intern("_error") {
250 return;
251 }
252 self.validate_identifier(ident);
253 let text = ident.name.to_string();
254 if text.starts_with('_') {
255 self.handler.emit_err(ParserError::identifier_cannot_start_with_underscore(ident.span));
256 }
257 if symbol_is_keyword(ident.name) {
258 self.emit_unexpected_str("an identifier", &text, ident.span);
259 }
260 }
261
262 fn to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
268 let ty = match node.kind() {
269 TYPE_PRIMITIVE => self.type_primitive_to_type(node)?,
270 TYPE_LOCATOR => self.type_locator_to_type(node)?,
271 TYPE_PATH => self.type_path_to_type(node)?,
272 TYPE_ARRAY => self.type_array_to_type(node)?,
273 TYPE_VECTOR => self.type_vector_to_type(node)?,
274 TYPE_TUPLE => self.type_tuple_to_type(node)?,
275 TYPE_OPTIONAL => self.type_optional_to_type(node)?,
276 TYPE_FINAL => self.type_final_to_type(node)?,
277 TYPE_MAPPING => self.type_mapping_to_type(node)?,
278 TYPE_DYN_RECORD => leo_ast::Type::DynRecord,
279 ERROR => {
280 leo_ast::Type::Err
282 }
283 kind => panic!("unexpected type node kind: {:?}", kind),
284 };
285 Ok(ty)
286 }
287
288 fn type_primitive_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
290 debug_assert_eq!(node.kind(), TYPE_PRIMITIVE);
291 let prim = tokens(node)
292 .next()
293 .and_then(|t| keyword_to_primitive_type(t.kind()))
294 .expect("TYPE_PRIMITIVE should contain a type keyword");
295 Ok(prim)
296 }
297
298 fn type_locator_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
302 debug_assert_eq!(node.kind(), TYPE_LOCATOR);
303
304 let all_idents: Vec<_> = tokens(node).filter(|t| t.kind() == IDENT).collect();
307 let Some(program_token) = all_idents.first() else {
308 panic!("TYPE_LOCATOR should contain at least a program IDENT: {:?}", node.text())
309 };
310
311 let kw_aleo_token =
313 tokens(node).find(|t| t.kind() == KW_ALEO).expect("TYPE_LOCATOR should contain `aleo` keyword");
314
315 let network_ident = leo_ast::Identifier {
316 name: Symbol::intern("aleo"),
317 span: self.token_span(&kw_aleo_token),
318 id: self.builder.next_id(),
319 };
320
321 let program_ident = self.to_identifier(program_token);
322 let program_id = leo_ast::ProgramId { name: program_ident, network: network_ident };
323
324 if all_idents.len() < 2 {
325 let span = self.content_span(node);
327 let path = leo_ast::Path::new(Some(program_id), Vec::new(), program_ident, span, self.builder.next_id());
328 Ok(leo_ast::CompositeType { path, const_arguments: Vec::new() }.into())
329 } else {
330 let name_token = all_idents.last().unwrap(); let qualifier: Vec<_> = all_idents[1..all_idents.len() - 1].iter().map(|t| self.to_identifier(t)).collect();
334 let type_ident = self.to_identifier(name_token);
335 let path_span = Span::new(program_id.name.span.lo, type_ident.span.hi);
336 let path = leo_ast::Path::new(Some(program_id), qualifier, type_ident, path_span, self.builder.next_id());
337 let (_type_parameters, const_arguments) = self.extract_const_arg_list(node)?;
338 Ok(leo_ast::CompositeType { path, const_arguments }.into())
339 }
340 }
341
342 fn type_path_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
346 debug_assert_eq!(node.kind(), TYPE_PATH);
347
348 let mut path_components = Vec::new();
350
351 for token in tokens(node) {
353 match token.kind() {
354 IDENT => {
355 path_components.push(self.to_identifier(&token));
356 }
357 COLON_COLON | L_BRACKET | R_BRACKET | LT | GT | COMMA | INTEGER => {}
359 kind if kind.is_trivia() => {}
360 kind => panic!("unexpected token in TYPE_PATH: {:?}", kind),
361 }
362 }
363
364 let (_type_parameters, const_arguments) = self.extract_const_arg_list(node)?;
366
367 let name = path_components.pop().expect("TYPE_PATH should have at least one identifier");
370 let path_span =
371 if let Some(first) = path_components.first() { Span::new(first.span.lo, name.span.hi) } else { name.span };
372 let path = leo_ast::Path::new(None, path_components, name, path_span, self.builder.next_id());
373 Ok(leo_ast::CompositeType { path, const_arguments }.into())
374 }
375
376 fn type_array_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
378 debug_assert_eq!(node.kind(), TYPE_ARRAY);
379
380 match children(node).find(|n| n.kind().is_type()) {
381 Some(element_node) => {
382 let element_type = self.to_type(&element_node)?;
383 let length_expr = self.array_length_to_expression(node)?;
384 Ok(leo_ast::ArrayType { element_type: Box::new(element_type), length: Box::new(length_expr) }.into())
385 }
386 None => {
387 let span = self.to_span(node);
389 self.emit_unexpected_str("element type", node.text(), span);
390 Ok(leo_ast::Type::Err)
391 }
392 }
393 }
394
395 fn type_vector_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
397 debug_assert_eq!(node.kind(), TYPE_VECTOR);
398
399 match children(node).find(|n| n.kind().is_type()) {
400 Some(element_node) => {
401 let element_type = self.to_type(&element_node)?;
402 Ok(leo_ast::VectorType { element_type: Box::new(element_type) }.into())
403 }
404 None => {
405 let span = self.to_span(node);
408 self.emit_unexpected_str("element type", node.text(), span);
409 Ok(leo_ast::Type::Err)
410 }
411 }
412 }
413
414 fn array_length_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
416 match children(node).find(|n| n.kind() == ARRAY_LENGTH) {
417 Some(length_node) => self.require_expression(&length_node, "array length"),
418 None => {
419 let span = self.to_span(node);
421 self.emit_unexpected_str("array length", node.text(), span);
422 Ok(self.error_expression(span))
423 }
424 }
425 }
426
427 fn integer_token_to_expression(&self, token: &SyntaxToken) -> Result<leo_ast::Expression> {
429 debug_assert_eq!(token.kind(), INTEGER);
430 let text = token.text();
431 let span = self.token_span(token);
432 let id = self.builder.next_id();
433
434 let suffixes = [
436 ("u128", leo_ast::IntegerType::U128),
437 ("u64", leo_ast::IntegerType::U64),
438 ("u32", leo_ast::IntegerType::U32),
439 ("u16", leo_ast::IntegerType::U16),
440 ("u8", leo_ast::IntegerType::U8),
441 ("i128", leo_ast::IntegerType::I128),
442 ("i64", leo_ast::IntegerType::I64),
443 ("i32", leo_ast::IntegerType::I32),
444 ("i16", leo_ast::IntegerType::I16),
445 ("i8", leo_ast::IntegerType::I8),
446 ];
447
448 for (suffix, int_type) in suffixes {
449 if text.ends_with(suffix) {
450 let value = text.strip_suffix(suffix).unwrap().to_string();
452 return Ok(leo_ast::Literal::integer(int_type, value, span, id).into());
453 }
454 }
455
456 Ok(leo_ast::Literal::unsuffixed(text.to_string(), span, id).into())
458 }
459
460 fn type_tuple_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
462 debug_assert_eq!(node.kind(), TYPE_TUPLE);
463 let span = self.to_span(node);
464
465 let type_nodes: Vec<_> = children(node).filter(|n| n.kind().is_type()).collect();
466
467 if type_nodes.is_empty() {
468 return Ok(leo_ast::Type::Unit);
470 }
471
472 let elements = type_nodes.iter().map(|n| self.to_type(n)).collect::<Result<Vec<_>>>()?;
473
474 if elements.len() == 1 {
475 self.handler.emit_err(ParserError::tuple_must_have_at_least_two_elements("type", span));
477 return Ok(elements.into_iter().next().unwrap());
479 }
480
481 Ok(leo_ast::TupleType::new(elements).into())
482 }
483
484 fn type_optional_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
486 debug_assert_eq!(node.kind(), TYPE_OPTIONAL);
487
488 let inner_node = children(node).find(|n| n.kind().is_type()).expect("optional type should have inner type");
489
490 let inner = self.to_type(&inner_node)?;
491 Ok(leo_ast::Type::Optional(leo_ast::OptionalType { inner: Box::new(inner) }))
492 }
493
494 fn type_final_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
496 debug_assert_eq!(node.kind(), TYPE_FINAL);
497
498 let type_nodes: Vec<_> = children(node).filter(|n| n.kind().is_type()).collect();
500
501 if type_nodes.is_empty() {
502 return Ok(leo_ast::FutureType::default().into());
504 }
505
506 let types = type_nodes.iter().map(|n| self.to_type(n)).collect::<Result<Vec<_>>>()?;
508
509 Ok(leo_ast::FutureType::new(types, None, true).into())
510 }
511
512 fn type_mapping_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
513 debug_assert_eq!(node.kind(), TYPE_MAPPING);
514 let mut type_nodes = children(node).filter(|n| n.kind().is_type());
515 let key = type_nodes.next().map(|n| self.to_type(&n)).transpose()?.unwrap_or(leo_ast::Type::Err);
516 let value = type_nodes.next().map(|n| self.to_type(&n)).transpose()?.unwrap_or(leo_ast::Type::Err);
517 Ok(leo_ast::Type::Mapping(leo_ast::MappingType { key: Box::new(key), value: Box::new(value) }))
518 }
519
520 fn to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
526 let span = self.content_span(node);
527
528 let expr = match node.kind() {
529 LITERAL_FIELD => self.suffixed_literal_to_expression(node, "field", leo_ast::Literal::field)?,
530 LITERAL_GROUP => self.suffixed_literal_to_expression(node, "group", leo_ast::Literal::group)?,
531 LITERAL_SCALAR => self.suffixed_literal_to_expression(node, "scalar", leo_ast::Literal::scalar)?,
532 LITERAL_INT => self.int_literal_to_expression(node)?,
533 LITERAL_STRING => self.string_literal_to_expression(node)?,
534 LITERAL_ADDRESS => self.address_literal_to_expression(node)?,
535 LITERAL_BOOL => self.bool_literal_to_expression(node)?,
536 LITERAL_NONE => leo_ast::Literal::none(span, self.builder.next_id()).into(),
537 LITERAL_IDENT => self.identifier_literal_to_expression(node)?,
538 BINARY_EXPR => self.binary_expr_to_expression(node)?,
539 UNARY_EXPR => self.unary_expr_to_expression(node)?,
540 CALL_EXPR => self.call_expr_to_expression(node)?,
541 DYNAMIC_CALL_EXPR => self.dynamic_call_expr_to_expression(node)?,
542 METHOD_CALL_EXPR => self.method_call_expr_to_expression(node)?,
543 FIELD_EXPR => self.field_expr_to_expression(node)?,
544 TUPLE_ACCESS_EXPR => self.tuple_access_expr_to_expression(node)?,
545 INDEX_EXPR => self.index_expr_to_expression(node)?,
546 CAST_EXPR => self.cast_expr_to_expression(node)?,
547 TERNARY_EXPR => self.ternary_expr_to_expression(node)?,
548 ARRAY_EXPR => self.array_expr_to_expression(node)?,
549 REPEAT_EXPR => self.repeat_expr_to_expression(node)?,
550 TUPLE_EXPR => self.tuple_expr_to_expression(node)?,
551 STRUCT_EXPR => self.struct_expr_to_expression(node)?,
552 STRUCT_LOCATOR_EXPR => self.struct_locator_expr_to_expression(node)?,
553 PATH_EXPR => self.path_expr_to_expression(node)?,
554 PATH_LOCATOR_EXPR => self.path_locator_expr_to_expression(node)?,
555 PROGRAM_REF_EXPR => self.program_ref_expr_to_expression(node)?,
556 SELF_EXPR => self.keyword_expr_to_path(node, sym::SelfLower)?,
557 BLOCK_KW_EXPR => self.keyword_expr_to_path(node, sym::block)?,
558 NETWORK_KW_EXPR => self.keyword_expr_to_path(node, sym::network)?,
559 PAREN_EXPR => {
560 if let Some(inner) = children(node).find(|n| n.kind().is_expression()) {
562 self.to_expression(&inner)?
563 } else {
564 self.emit_unexpected_str("expression in parentheses", node.text(), span);
566 self.error_expression(span)
567 }
568 }
569 FINAL_EXPR => self.final_expr_to_expression(node)?,
571 ROOT => {
573 if let Some(inner) = children(node).find(|n| n.kind().is_expression()) {
574 self.to_expression(&inner)?
575 } else {
576 self.error_expression(span)
578 }
579 }
580 ERROR => self.error_expression(span),
583 kind => panic!("unexpected expression kind: {:?}", kind),
584 };
585
586 Ok(expr)
587 }
588
589 fn suffixed_literal_to_expression(
591 &self,
592 node: &SyntaxNode,
593 suffix: &str,
594 ctor: fn(String, Span, leo_ast::NodeID) -> leo_ast::Literal,
595 ) -> Result<leo_ast::Expression> {
596 let span = self.content_span(node);
597 let id = self.builder.next_id();
598 let token = tokens(node).next().expect("literal node should have a token");
599 let text = token.text();
600 self.validate_hexbin_literal(text, suffix.len() as u32, span);
601 let value = text.strip_suffix(suffix).unwrap();
602 Ok(ctor(value.to_string(), span, id).into())
603 }
604
605 fn int_literal_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
607 let token = tokens(node).next().expect("LITERAL_INT should have a token");
608 self.integer_token_to_expression(&token)
609 }
610
611 fn string_literal_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
613 let span = self.content_span(node);
614 let id = self.builder.next_id();
615 let token = tokens(node).next().expect("LITERAL_STRING should have a token");
616 Ok(leo_ast::Literal::string(token.text().to_string(), span, id).into())
617 }
618
619 fn identifier_literal_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
621 let span = self.content_span(node);
622 let id = self.builder.next_id();
623 let token = tokens(node).next().expect("LITERAL_IDENT should have a token");
624 let text = token.text();
626 let content = &text[1..text.len() - 1];
627 Ok(leo_ast::Literal::identifier(content.to_string(), span, id).into())
628 }
629
630 fn address_literal_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
632 let span = self.content_span(node);
633 let id = self.builder.next_id();
634 let token = tokens(node).next().expect("LITERAL_ADDRESS should have a token");
635 let text = token.text();
636 if !text.contains(".aleo") && text.parse::<Address<TestnetV0>>().is_err() {
638 self.handler.emit_err(ParserError::invalid_address_lit(text, span));
639 }
640 Ok(leo_ast::Literal::address(text.to_string(), span, id).into())
641 }
642
643 fn bool_literal_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
645 let span = self.content_span(node);
646 let id = self.builder.next_id();
647 let token = tokens(node).next().expect("LITERAL_BOOL should have a token");
648 let value = token.kind() == KW_TRUE;
649 Ok(leo_ast::Literal::boolean(value, span, id).into())
650 }
651
652 fn binary_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
654 debug_assert_eq!(node.kind(), BINARY_EXPR);
655 let span = self.content_span(node);
656 let id = self.builder.next_id();
657
658 let mut operands = children(node).filter(|n| n.kind().is_expression() || n.kind().is_type());
659
660 let op_token = match tokens(node).find(|t| t.kind().is_operator() || t.kind() == KW_AS) {
662 Some(token) => token,
663 None => {
664 self.emit_unexpected_str("operator in binary expression", node.text(), span);
665 return Ok(self.error_expression(span));
666 }
667 };
668
669 let op = token_to_binary_op(op_token.kind());
670
671 let left = match operands.next() {
673 Some(left_node) => self.to_expression(&left_node)?,
674 None => {
675 self.emit_unexpected_str("left operand in binary expression", node.text(), span);
676 return Ok(self.error_expression(span));
677 }
678 };
679
680 if op_token.kind() == KW_AS {
682 self.emit_unexpected_str("cast expression", "binary AS expression", span);
683 return Ok(self.error_expression(span));
684 }
685
686 let right = match operands.next() {
688 Some(right_node) => self.to_expression(&right_node)?,
689 None => {
690 self.emit_unexpected_str("right operand in binary expression", node.text(), span);
691 return Ok(self.error_expression(span));
692 }
693 };
694
695 Ok(leo_ast::BinaryExpression { left, right, op, span, id }.into())
696 }
697
698 fn unary_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
700 debug_assert_eq!(node.kind(), UNARY_EXPR);
701 let span = self.content_span(node);
702 let id = self.builder.next_id();
703
704 let Some(op_token) = tokens(node).find(|t| matches!(t.kind(), BANG | MINUS)) else {
706 self.emit_unexpected_str("operator in unary expression", node.text(), span);
707 return Ok(self.error_expression(span));
708 };
709
710 let op = if op_token.kind() == BANG { leo_ast::UnaryOperation::Not } else { leo_ast::UnaryOperation::Negate };
711
712 let Some(operand) = children(node).find(|n| n.kind().is_expression()) else {
714 self.emit_unexpected_str("operand in unary expression", node.text(), span);
715 return Ok(self.error_expression(span));
716 };
717
718 let mut receiver = self.to_expression(&operand)?;
719
720 if op == leo_ast::UnaryOperation::Negate
722 && let leo_ast::Expression::Literal(leo_ast::Literal {
723 variant:
724 leo_ast::LiteralVariant::Integer(_, ref mut string)
725 | leo_ast::LiteralVariant::Field(ref mut string)
726 | leo_ast::LiteralVariant::Group(ref mut string)
727 | leo_ast::LiteralVariant::Scalar(ref mut string),
728 span: ref mut lit_span,
729 ..
730 }) = receiver
731 && !string.starts_with('-')
732 {
733 string.insert(0, '-');
734 *lit_span = span;
735 return Ok(receiver);
736 }
737
738 Ok(leo_ast::UnaryExpression { receiver, op, span, id }.into())
739 }
740
741 fn extract_const_arg_list(&self, node: &SyntaxNode) -> Result<ConstArgList> {
748 let mut type_parameters = Vec::new();
749 let mut const_arguments = Vec::new();
750 if let Some(arg_list) = children(node).find(|n| n.kind() == CONST_ARG_LIST) {
751 for child in children(&arg_list) {
752 if child.kind() == DYNAMIC_CALL_RETURN_TYPE {
753 if let Some(type_node) = children(&child).find(|n| n.kind().is_type()) {
756 let span = self.content_span(&child);
757 let ty = self.to_type(&type_node)?;
758 type_parameters.push((ty, span));
759 }
760 } else if child.kind().is_type() {
761 let span = self.content_span(&child);
762 let ty = self.to_type(&child)?;
763 type_parameters.push((ty, span));
764 } else if child.kind().is_expression() {
765 let expr = self.to_expression(&child)?;
766 const_arguments.push(expr);
767 }
768 }
769 }
770 Ok((type_parameters, const_arguments))
771 }
772
773 fn extract_dynamic_call_types(
783 &self,
784 callee_node: &SyntaxNode,
785 type_parameters: &[(leo_ast::Type, Span)],
786 ) -> Result<(AnnotatedTypes, AnnotatedTypes)> {
787 let Some(arg_list) = children(callee_node).find(|n| n.kind() == CONST_ARG_LIST) else {
788 return Ok((Vec::new(), Vec::new()));
789 };
790
791 let mut all_entries = Vec::new();
793
794 for child in children(&arg_list) {
795 if child.kind() == DYNAMIC_CALL_RETURN_TYPE {
796 let mode = tokens(&child).find_map(|tok| token_kind_to_mode(tok.kind())).unwrap_or(leo_ast::Mode::None);
797 all_entries.push(mode);
798 } else if child.kind().is_type() {
799 all_entries.push(leo_ast::Mode::None);
800 }
801 }
802
803 if type_parameters.is_empty() {
805 return Ok((Vec::new(), Vec::new()));
806 }
807
808 let mut input_types = Vec::new();
809 let mut return_types = Vec::new();
810
811 let last_idx = type_parameters.len() - 1;
812 for (i, ((ty, sp), mode)) in type_parameters.iter().zip(all_entries.iter()).enumerate() {
813 if i < last_idx {
814 input_types.push((*mode, ty.clone(), *sp));
816 } else {
817 match ty {
822 leo_ast::Type::Unit => {}
823 leo_ast::Type::Tuple(tuple) => {
824 for elem in tuple.elements() {
825 return_types.push((*mode, elem.clone(), *sp));
826 }
827 }
828 _ => {
829 return_types.push((*mode, ty.clone(), *sp));
830 }
831 }
832 }
833 }
834
835 Ok((input_types, return_types))
836 }
837
838 fn call_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
840 debug_assert_eq!(node.kind(), CALL_EXPR);
841 let span = self.content_span(node);
842 let id = self.builder.next_id();
843
844 let mut child_iter = children(node);
846 let callee_node = child_iter.next().expect("call expr should have callee");
847
848 let function = match callee_node.kind() {
849 PATH_LOCATOR_EXPR => self.locator_tokens_to_path(&callee_node)?,
850 _ => self.path_expr_to_path(&callee_node)?,
851 };
852
853 let arguments = children(node)
855 .skip(1) .filter(|n| n.kind().is_expression())
857 .map(|n| self.to_expression(&n))
858 .collect::<Result<Vec<_>>>()?;
859
860 let (type_parameters, const_arguments) = self.extract_const_arg_list(&callee_node)?;
863
864 if function.user_program().is_none() && function.qualifier().len() == 1 {
868 let module = function.qualifier()[0].name;
869 let name = function.identifier().name;
870 if let Some(intrinsic_name) = leo_ast::Intrinsic::convert_path_symbols(module, name) {
871 return Ok(leo_ast::IntrinsicExpression {
872 name: intrinsic_name,
873 type_parameters,
874 input_types: Vec::new(),
875 return_types: Vec::new(),
876 arguments,
877 span,
878 id,
879 }
880 .into());
881 }
882 }
883
884 if function.user_program().is_none() && function.qualifier().is_empty() {
887 let name = function.identifier().name;
888 if leo_ast::Intrinsic::from_symbol(name, &type_parameters).is_some() {
889 let (input_types, return_types) = if name == leo_span::sym::_dynamic_call {
892 self.extract_dynamic_call_types(&callee_node, &type_parameters)?
893 } else {
894 (Vec::new(), Vec::new())
895 };
896 return Ok(leo_ast::IntrinsicExpression {
897 name,
898 type_parameters,
899 input_types,
900 return_types,
901 arguments,
902 span,
903 id,
904 }
905 .into());
906 }
907 }
908
909 Ok(leo_ast::CallExpression { function, const_arguments, arguments, span, id }.into())
910 }
911
912 fn dynamic_call_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
914 debug_assert_eq!(node.kind(), DYNAMIC_CALL_EXPR);
915 let span = self.content_span(node);
916 let id = self.builder.next_id();
917
918 let interface = children(node)
919 .filter(|n| n.kind().is_type())
920 .map(|n| self.to_type(&n))
921 .next()
922 .expect("Parser guarantees a type")?;
923
924 let function = if let Some(token) = tokens(node).find(|t| t.kind() == IDENT) {
925 self.to_identifier(&token)
926 } else {
927 self.error_identifier(span)
928 };
929
930 let separator_offset = tokens(node).filter(|t| t.kind() == COLON_COLON).last().map(|t| t.text_range().start());
936
937 let expr_children: Vec<_> = children(node).filter(|n| n.kind().is_expression()).collect();
938
939 let mut pre_sep = Vec::new();
940 let mut post_sep = Vec::new();
941 for child in &expr_children {
942 if let Some(sep_off) = separator_offset {
943 if child.text_range().start() < sep_off {
944 pre_sep.push(child);
945 } else {
946 post_sep.push(child);
947 }
948 } else {
949 pre_sep.push(child);
951 }
952 }
953
954 let target = if let Some(target_node) = pre_sep.first() {
955 self.to_expression(target_node)?
956 } else {
957 self.error_expression(span)
958 };
959
960 let network =
961 if let Some(network_node) = pre_sep.get(1) { Some(self.to_expression(network_node)?) } else { None };
962
963 let arguments = post_sep.iter().map(|n| self.to_expression(n)).collect::<Result<Vec<_>>>()?;
964
965 Ok(leo_ast::DynamicCallExpression { interface, target_program: target, network, function, arguments, span, id }
966 .into())
967 }
968
969 fn method_call_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
973 debug_assert_eq!(node.kind(), METHOD_CALL_EXPR);
974 let span = self.content_span(node);
975 let id = self.builder.next_id();
976
977 let mut expr_children = children(node).filter(|n| n.kind().is_expression());
979 let receiver = match expr_children.next() {
980 Some(receiver_node) => self.to_expression(&receiver_node)?,
981 None => {
982 self.emit_unexpected_str("receiver in method call", node.text(), span);
983 return Ok(self.error_expression(span));
984 }
985 };
986
987 let method_name = match find_name_after_dot(node) {
993 Some(method_token) if method_token.kind() == IDENT => self.to_identifier(&method_token),
994 Some(method_token) => {
995 let token_span = self.token_span(&method_token);
996 self.emit_unexpected_str("identifier", method_token.text(), token_span);
997 self.error_identifier(token_span)
998 }
999 None => {
1000 self.emit_unexpected_str("method name in method call", node.text(), span);
1001 return Ok(self.error_expression(span));
1002 }
1003 };
1004
1005 let mut args: Vec<_> = expr_children.map(|n| self.to_expression(&n)).collect::<Result<Vec<_>>>()?;
1007
1008 if args.is_empty() {
1010 if let Some(op) = leo_ast::UnaryOperation::from_symbol(method_name.name) {
1011 return Ok(leo_ast::UnaryExpression { span, op, receiver, id }.into());
1012 }
1013 } else if args.len() == 1
1014 && let Some(op) = leo_ast::BinaryOperation::from_symbol(method_name.name)
1015 {
1016 return Ok(leo_ast::BinaryExpression { span, op, left: receiver, right: args.pop().unwrap(), id }.into());
1017 }
1018
1019 let method = method_name.name;
1025 let all_args = || std::iter::once(receiver.clone()).chain(args.clone()).collect::<Vec<_>>();
1026
1027 let intrinsic_name = match args.len() {
1029 2 => leo_ast::Intrinsic::convert_path_symbols(sym::signature, method),
1030 0 => leo_ast::Intrinsic::convert_path_symbols(sym::Final, method)
1031 .or_else(|| leo_ast::Intrinsic::convert_path_symbols(sym::Optional, method)),
1032 1 => leo_ast::Intrinsic::convert_path_symbols(sym::Optional, method),
1033 _ => None,
1034 };
1035 if let Some(intrinsic_name) = intrinsic_name {
1036 return Ok(self.intrinsic_expression(intrinsic_name, all_args(), span));
1037 }
1038
1039 if method == sym::get && args.len() == 1 {
1042 return Ok(self.intrinsic_expression(Symbol::intern("__unresolved_get"), all_args(), span));
1043 }
1044 if method == sym::set && args.len() == 2 {
1045 return Ok(self.intrinsic_expression(Symbol::intern("__unresolved_set"), all_args(), span));
1046 }
1047
1048 for module in [sym::Vector, sym::Mapping] {
1050 if let Some(intrinsic_name) = leo_ast::Intrinsic::convert_path_symbols(module, method) {
1051 return Ok(self.intrinsic_expression(intrinsic_name, all_args(), span));
1052 }
1053 }
1054
1055 self.handler.emit_err(ParserError::invalid_method_call(receiver, method_name, args.len(), span));
1057 Ok(self.error_expression(span))
1058 }
1059
1060 fn tuple_access_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1062 debug_assert_eq!(node.kind(), TUPLE_ACCESS_EXPR);
1063 let span = self.content_span(node);
1064 let id = self.builder.next_id();
1065
1066 let inner = if let Some(inner_node) = children(node).find(|n| n.kind().is_expression()) {
1067 self.to_expression(&inner_node)?
1068 } else {
1069 self.emit_unexpected_str("expression in tuple access", node.text(), span);
1070 return Ok(self.error_expression(span));
1071 };
1072
1073 let index_token = match tokens(node).find(|t| t.kind() == INTEGER) {
1074 Some(token) => token,
1075 None => {
1076 self.emit_unexpected_str("tuple index", node.text(), span);
1077 return Ok(self.error_expression(span));
1078 }
1079 };
1080
1081 let index_text = index_token.text().replace('_', "");
1082 let index: usize = match index_text.parse() {
1083 Ok(idx) => idx,
1084 Err(_) => {
1085 self.emit_unexpected_str("valid tuple index", index_text, span);
1086 return Ok(self.error_expression(span));
1087 }
1088 };
1089 Ok(leo_ast::TupleAccess { tuple: inner, index: index.into(), span, id }.into())
1090 }
1091
1092 fn field_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1094 debug_assert_eq!(node.kind(), FIELD_EXPR);
1095 let span = self.content_span(node);
1096 let id = self.builder.next_id();
1097
1098 let (inner, first_child_kind) = match children(node).find(|n| n.kind().is_expression()) {
1100 Some(n) => {
1101 let kind = n.kind();
1102 (self.to_expression(&n)?, kind)
1103 }
1104 None => {
1105 self.emit_unexpected_str("expression in field access", node.text(), span);
1106 return Ok(self.error_expression(span));
1107 }
1108 };
1109
1110 let field_token = match find_name_after_dot(node) {
1113 Some(token) => token,
1114 None => {
1115 self.emit_unexpected_str("field name in field access", node.text(), span);
1116 return Ok(self.error_expression(span));
1117 }
1118 };
1119
1120 if field_token.kind() == KW_ALEO
1124 && let leo_ast::Expression::Path(ref path) = inner
1125 && path.user_program().is_none()
1126 && path.qualifier().is_empty()
1127 {
1128 let full_name = format!("{}.aleo", path.identifier().name);
1129 return Ok(leo_ast::Literal::address(full_name, span, id).into());
1130 }
1131
1132 let field_name = Symbol::intern(field_token.text());
1134
1135 let special = match (first_child_kind, field_name) {
1136 (SELF_EXPR, sym::address) => Some(sym::_self_address),
1137 (SELF_EXPR, sym::caller) => Some(sym::_self_caller),
1138 (SELF_EXPR, sym::checksum) => Some(sym::_self_checksum),
1139 (SELF_EXPR, sym::edition) => Some(sym::_self_edition),
1140 (SELF_EXPR, sym::id) => Some(sym::_self_id),
1141 (SELF_EXPR, sym::program_owner) => Some(sym::_self_program_owner),
1142 (SELF_EXPR, sym::signer) => Some(sym::_self_signer),
1143 (BLOCK_KW_EXPR, sym::height) => Some(sym::_block_height),
1144 (BLOCK_KW_EXPR, sym::timestamp) => Some(sym::_block_timestamp),
1145 (NETWORK_KW_EXPR, sym::id) => Some(sym::_network_id),
1146 (SELF_EXPR | BLOCK_KW_EXPR | NETWORK_KW_EXPR, _) => {
1147 self.handler.emit_err(ParserError::custom("Unsupported special access", span));
1148 return Ok(self.error_expression(span));
1149 }
1150 _ => None,
1151 };
1152
1153 if let Some(intrinsic_name) = special {
1154 return Ok(self.intrinsic_expression(intrinsic_name, Vec::new(), span));
1155 }
1156
1157 let name = leo_ast::Identifier {
1159 name: Symbol::intern(field_token.text()),
1160 span: self.token_span(&field_token),
1161 id: self.builder.next_id(),
1162 };
1163 Ok(leo_ast::MemberAccess { inner, name, span, id }.into())
1164 }
1165
1166 fn index_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1168 debug_assert_eq!(node.kind(), INDEX_EXPR);
1169 let span = self.content_span(node);
1170 let id = self.builder.next_id();
1171
1172 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1173
1174 let array = match exprs.next() {
1175 Some(n) => self.to_expression(&n)?,
1176 None => {
1177 self.emit_unexpected_str("array in index expression", node.text(), span);
1178 return Ok(self.error_expression(span));
1179 }
1180 };
1181
1182 let index = match exprs.next() {
1183 Some(n) => self.to_expression(&n)?,
1184 None => {
1185 self.emit_unexpected_str("index in index expression", node.text(), span);
1186 return Ok(self.error_expression(span));
1187 }
1188 };
1189
1190 Ok(leo_ast::ArrayAccess { array, index, span, id }.into())
1191 }
1192
1193 fn cast_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1195 debug_assert_eq!(node.kind(), CAST_EXPR);
1196 let span = self.content_span(node);
1197 let id = self.builder.next_id();
1198
1199 let Some(expr_node) = children(node).find(|n| n.kind().is_expression()) else {
1201 self.emit_unexpected_str("expression in cast", node.text(), span);
1202 return Ok(self.error_expression(span));
1203 };
1204 let expression = self.to_expression(&expr_node)?;
1205
1206 let Some(type_node) = children(node).find(|n| n.kind().is_type()) else {
1208 self.emit_unexpected_str("type in cast expression", node.text(), span);
1209 return Ok(self.error_expression(span));
1210 };
1211 let type_ = self.to_type(&type_node)?;
1212
1213 Ok(leo_ast::CastExpression { expression, type_, span, id }.into())
1214 }
1215
1216 fn ternary_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1218 debug_assert_eq!(node.kind(), TERNARY_EXPR);
1219 let span = self.content_span(node);
1220 let id = self.builder.next_id();
1221
1222 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1223
1224 let condition = match exprs.next() {
1225 Some(n) => self.to_expression(&n)?,
1226 None => {
1227 self.emit_unexpected_str("condition in ternary expression", node.text(), span);
1228 return Ok(self.error_expression(span));
1229 }
1230 };
1231
1232 let if_true = match exprs.next() {
1233 Some(n) => self.to_expression(&n)?,
1234 None => {
1235 self.emit_unexpected_str("true branch in ternary expression", node.text(), span);
1236 return Ok(self.error_expression(span));
1237 }
1238 };
1239
1240 let if_false = match exprs.next() {
1241 Some(n) => self.to_expression(&n)?,
1242 None => {
1243 self.emit_unexpected_str("false branch in ternary expression", node.text(), span);
1244 return Ok(self.error_expression(span));
1245 }
1246 };
1247
1248 Ok(leo_ast::TernaryExpression { condition, if_true, if_false, span, id }.into())
1249 }
1250
1251 fn array_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1253 debug_assert_eq!(node.kind(), ARRAY_EXPR);
1254 let span = self.content_span(node);
1255 let id = self.builder.next_id();
1256
1257 let elements = children(node)
1258 .filter(|n| n.kind().is_expression())
1259 .map(|n| self.to_expression(&n))
1260 .collect::<Result<Vec<_>>>()?;
1261
1262 Ok(leo_ast::ArrayExpression { elements, span, id }.into())
1263 }
1264
1265 fn repeat_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1267 debug_assert_eq!(node.kind(), REPEAT_EXPR);
1268 let span = self.content_span(node);
1269 let id = self.builder.next_id();
1270
1271 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1272 let expr = match exprs.next() {
1273 Some(n) => self.to_expression(&n)?,
1274 None => {
1275 self.emit_unexpected_str("expression in repeat", node.text(), span);
1276 return Ok(self.error_expression(span));
1277 }
1278 };
1279 let count = match exprs.next() {
1280 Some(n) => self.to_expression(&n)?,
1281 None => {
1282 self.emit_unexpected_str("repeat count", node.text(), span);
1283 return Ok(self.error_expression(span));
1284 }
1285 };
1286
1287 Ok(leo_ast::RepeatExpression { expr, count, span, id }.into())
1288 }
1289
1290 fn tuple_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1292 debug_assert_eq!(node.kind(), TUPLE_EXPR);
1293 let span = self.content_span(node);
1294 let id = self.builder.next_id();
1295
1296 let elements: Vec<_> = children(node)
1297 .filter(|n| n.kind().is_expression())
1298 .map(|n| self.to_expression(&n))
1299 .collect::<Result<Vec<_>>>()?;
1300
1301 match elements.len() {
1302 0 => {
1303 self.handler.emit_err(ParserError::tuple_must_have_at_least_two_elements("expression", span));
1305 Ok(leo_ast::UnitExpression { span, id }.into())
1307 }
1308 1 => {
1309 self.handler.emit_err(ParserError::tuple_must_have_at_least_two_elements("expression", span));
1311 Ok(elements.into_iter().next().unwrap())
1313 }
1314 _ => Ok(leo_ast::TupleExpression { elements, span, id }.into()),
1315 }
1316 }
1317
1318 fn composite_expression_from_path(
1321 &self,
1322 node: &SyntaxNode,
1323 path: leo_ast::Path,
1324 span: Span,
1325 id: leo_ast::NodeID,
1326 ) -> Result<leo_ast::Expression> {
1327 let members = children(node)
1328 .filter(|n| matches!(n.kind(), STRUCT_FIELD_INIT | STRUCT_FIELD_SHORTHAND))
1329 .map(|n| self.struct_field_init_to_member(&n))
1330 .collect::<Result<Vec<_>>>()?;
1331 let (_type_parameters, const_arguments) = self.extract_const_arg_list(node)?;
1332 Ok(leo_ast::CompositeExpression { path, const_arguments, members, span, id }.into())
1333 }
1334
1335 fn struct_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1337 debug_assert_eq!(node.kind(), STRUCT_EXPR);
1338 let span = self.content_span(node);
1339 let id = self.builder.next_id();
1340 let path = self.struct_expr_to_path(node)?;
1341 self.composite_expression_from_path(node, path, span, id)
1342 }
1343
1344 fn struct_expr_to_path(&self, node: &SyntaxNode) -> Result<leo_ast::Path> {
1346 let fallback_span = self.content_span(node);
1347
1348 let mut path_components = Vec::new();
1350 for token in tokens(node) {
1351 if token.kind() == L_BRACE {
1352 break;
1353 }
1354 if token.kind() == IDENT {
1355 path_components.push(self.to_identifier(&token));
1356 }
1357 }
1358
1359 let path_span = match (path_components.first(), path_components.last()) {
1360 (Some(first), Some(last)) => Span::new(first.span.lo, last.span.hi),
1361 _ => fallback_span,
1362 };
1363
1364 let name = match path_components.pop() {
1365 Some(name) => name,
1366 None => {
1367 self.emit_unexpected_str("type name in struct expression", node.text(), fallback_span);
1368 self.error_identifier(fallback_span)
1369 }
1370 };
1371 Ok(leo_ast::Path::new(None, path_components, name, path_span, self.builder.next_id()))
1372 }
1373
1374 fn struct_locator_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1376 let span = self.content_span(node);
1377 let id = self.builder.next_id();
1378 let path = self.locator_tokens_to_path(node)?;
1379 self.composite_expression_from_path(node, path, span, id)
1380 }
1381
1382 fn path_locator_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1384 let path = self.locator_tokens_to_path(node)?;
1385 Ok(leo_ast::Expression::Path(path))
1386 }
1387
1388 fn locator_tokens_to_path(&self, node: &SyntaxNode) -> Result<leo_ast::Path> {
1395 let span = self.to_span(node);
1396 let all_idents: Vec<_> = tokens(node).filter(|t| t.kind() == IDENT).collect();
1397
1398 let program_ident = match all_idents.first() {
1400 Some(t) => self.to_identifier(t),
1401 None => {
1402 self.emit_unexpected_str("program name", node.text(), span);
1403 self.error_identifier(span)
1404 }
1405 };
1406
1407 let network_ident = leo_ast::Identifier {
1409 name: Symbol::intern("aleo"),
1410 span: tokens(node).find(|t| t.kind() == KW_ALEO).map(|t| self.token_span(&t)).unwrap_or(span),
1411 id: self.builder.next_id(),
1412 };
1413
1414 let program = leo_ast::ProgramId { name: program_ident, network: network_ident };
1416
1417 let (qualifier, name) = if all_idents.len() < 2 {
1421 self.emit_unexpected_str("identifier", node.text(), span);
1422 (Vec::new(), self.error_identifier(span))
1423 } else {
1424 let name = self.to_identifier(all_idents.last().unwrap()); let qualifier: Vec<_> = all_idents[1..all_idents.len() - 1].iter().map(|t| self.to_identifier(t)).collect();
1426 (qualifier, name)
1427 };
1428
1429 let path_span = Span::new(program.name.span.lo, name.span.hi);
1430 Ok(leo_ast::Path::new(Some(program), qualifier, name, path_span, self.builder.next_id()))
1431 }
1432
1433 fn struct_field_init_to_member(&self, node: &SyntaxNode) -> Result<leo_ast::CompositeFieldInitializer> {
1435 debug_assert!(matches!(node.kind(), STRUCT_FIELD_INIT | STRUCT_FIELD_SHORTHAND));
1436 let span = self.content_span(node);
1437 let id = self.builder.next_id();
1438
1439 let Some(ident_token) = tokens(node).find(|t| t.kind() == IDENT) else {
1440 self.emit_unexpected_str("identifier in struct field", node.text(), span);
1441 return Ok(leo_ast::CompositeFieldInitializer {
1442 identifier: self.error_identifier(span),
1443 expression: None,
1444 span,
1445 id,
1446 });
1447 };
1448 let identifier = self.to_identifier(&ident_token);
1449
1450 let expression = if node.kind() == STRUCT_FIELD_INIT {
1451 children(node).find(|n| n.kind().is_expression()).map(|n| self.to_expression(&n)).transpose()?
1452 } else {
1453 None
1454 };
1455
1456 Ok(leo_ast::CompositeFieldInitializer { identifier, expression, span, id })
1457 }
1458
1459 fn program_ref_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1461 debug_assert_eq!(node.kind(), PROGRAM_REF_EXPR);
1462 let span = self.content_span(node);
1463 let id = self.builder.next_id();
1464 let text: String = tokens(node).map(|t| t.text().to_string()).collect();
1465 Ok(leo_ast::Literal::address(text, span, id).into())
1466 }
1467
1468 fn path_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1470 debug_assert_eq!(node.kind(), PATH_EXPR);
1471
1472 let path = self.path_expr_to_path(node)?;
1473 let span = self.trimmed_span(node);
1474 let id = self.builder.next_id();
1475
1476 if path.user_program().is_none()
1478 && path.qualifier().len() == 1
1479 && path.qualifier()[0].name == sym::group
1480 && path.identifier().name == sym::GEN
1481 {
1482 return Ok(self.intrinsic_expression(sym::_group_gen, Vec::new(), span));
1483 }
1484
1485 if path.user_program().is_none() && path.qualifier().is_empty() {
1488 let name_text = path.identifier().name.to_string();
1489 if name_text.starts_with("sign1") && name_text.parse::<Signature<TestnetV0>>().is_ok() {
1490 return Ok(leo_ast::Literal::signature(name_text, span, id).into());
1491 }
1492 if name_text.starts_with('_') {
1495 self.handler.emit_err(ParserError::identifier_cannot_start_with_underscore(span));
1496 return Ok(self.error_expression(span));
1497 }
1498 }
1499
1500 Ok(leo_ast::Expression::Path(path))
1501 }
1502
1503 fn keyword_expr_to_path(&self, node: &SyntaxNode, name: Symbol) -> Result<leo_ast::Expression> {
1505 let span = self.trimmed_span(node);
1506 let ident = leo_ast::Identifier { name, span, id: self.builder.next_id() };
1507 let path = leo_ast::Path::new(None, Vec::new(), ident, span, self.builder.next_id());
1508 Ok(leo_ast::Expression::Path(path))
1509 }
1510
1511 fn final_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1513 debug_assert_eq!(node.kind(), FINAL_EXPR);
1514 let span = self.content_span(node);
1515 let id = self.builder.next_id();
1516
1517 if let Some(block_node) = children(node).find(|n| n.kind() == BLOCK) {
1519 let block = self.to_block(&block_node)?;
1520 Ok(leo_ast::AsyncExpression { block, span, id }.into())
1521 } else {
1522 self.emit_unexpected_str("block in final expression", node.text(), span);
1524 Ok(self.error_expression(span))
1525 }
1526 }
1527
1528 fn path_expr_to_path(&self, node: &SyntaxNode) -> Result<leo_ast::Path> {
1536 let span = self.trimmed_span(node);
1537
1538 let mut path_components = Vec::new();
1540 for token in tokens(node) {
1541 match token.kind() {
1542 IDENT => {
1543 let text = token.text();
1544 if text.contains("::") {
1548 let token_span = self.token_span(&token);
1549 let mut offset = token_span.lo;
1550 for (i, segment) in text.split("::").enumerate() {
1551 if i > 0 {
1552 offset += 2; }
1554 let seg_span = Span::new(offset, offset + segment.len() as u32);
1555 path_components.push(leo_ast::Identifier {
1556 name: Symbol::intern(segment),
1557 span: seg_span,
1558 id: self.builder.next_id(),
1559 });
1560 offset += segment.len() as u32;
1561 }
1562 } else {
1563 path_components.push(self.to_identifier(&token));
1564 }
1565 }
1566 kind => {
1567 if let Some(name) = keyword_to_path_symbol(kind) {
1568 path_components.push(leo_ast::Identifier {
1569 name,
1570 span: self.token_span(&token),
1571 id: self.builder.next_id(),
1572 });
1573 }
1574 }
1575 }
1576 }
1577
1578 let name = match path_components.pop() {
1579 Some(name) => name,
1580 None => {
1581 self.emit_unexpected_str("identifier in path", node.text(), span);
1582 self.error_identifier(span)
1583 }
1584 };
1585 Ok(leo_ast::Path::new(None, path_components, name, span, self.builder.next_id()))
1586 }
1587
1588 fn to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1594 let span = self.to_span(node);
1595 let id = self.builder.next_id();
1596
1597 let stmt = match node.kind() {
1598 LET_STMT => self.let_stmt_to_statement(node)?,
1599 CONST_STMT => self.const_stmt_to_statement(node)?,
1600 RETURN_STMT => self.return_stmt_to_statement(node)?,
1601 EXPR_STMT => self.expr_stmt_to_statement(node)?,
1602 ASSIGN_STMT => self.simple_assign_to_statement(node)?,
1603 COMPOUND_ASSIGN_STMT => self.compound_assign_to_statement(node)?,
1604 IF_STMT => self.if_stmt_to_statement(node)?,
1605 FOR_STMT | FOR_INCLUSIVE_STMT => self.for_stmt_to_statement(node)?,
1606 BLOCK => self.to_block(node)?.into(),
1607 ASSERT_STMT => {
1608 let expression = self.require_expression(node, "expression in assert")?;
1609 leo_ast::AssertStatement { variant: leo_ast::AssertVariant::Assert(expression), span, id }.into()
1610 }
1611 ASSERT_EQ_STMT => {
1612 self.assert_binary_to_statement(node, "assert_eq", span, id, leo_ast::AssertVariant::AssertEq)?
1613 }
1614 ASSERT_NEQ_STMT => {
1615 self.assert_binary_to_statement(node, "assert_neq", span, id, leo_ast::AssertVariant::AssertNeq)?
1616 }
1617 ROOT => {
1619 if let Some(inner) = children(node).find(|n| n.kind().is_statement()) {
1620 self.to_statement(&inner)?
1621 } else {
1622 leo_ast::ExpressionStatement { expression: self.error_expression(span), span, id }.into()
1624 }
1625 }
1626 ERROR => leo_ast::ExpressionStatement { expression: self.error_expression(span), span, id }.into(),
1629 kind => panic!("unexpected statement kind: {:?}", kind),
1630 };
1631
1632 Ok(stmt)
1633 }
1634
1635 fn assert_binary_to_statement(
1637 &self,
1638 node: &SyntaxNode,
1639 label: &str,
1640 span: Span,
1641 id: leo_ast::NodeID,
1642 make_variant: fn(leo_ast::Expression, leo_ast::Expression) -> leo_ast::AssertVariant,
1643 ) -> Result<leo_ast::Statement> {
1644 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1645 let e0 = match exprs.next() {
1646 Some(expr) => self.to_expression(&expr)?,
1647 None => {
1648 self.emit_unexpected_str(&format!("first expression in {label}"), node.text(), span);
1649 self.error_expression(span)
1650 }
1651 };
1652 let e1 = match exprs.next() {
1653 Some(expr) => self.to_expression(&expr)?,
1654 None => {
1655 self.emit_unexpected_str(&format!("second expression in {label}"), node.text(), span);
1656 self.error_expression(span)
1657 }
1658 };
1659 Ok(leo_ast::AssertStatement { variant: make_variant(e0, e1), span, id }.into())
1660 }
1661
1662 fn to_block(&self, node: &SyntaxNode) -> Result<leo_ast::Block> {
1664 debug_assert_eq!(node.kind(), BLOCK);
1665 let span = self.to_span(node);
1666 let id = self.builder.next_id();
1667
1668 let statements = children(node)
1669 .filter(|n| n.kind().is_statement())
1670 .map(|n| self.to_statement(&n))
1671 .collect::<Result<Vec<_>>>()?;
1672
1673 Ok(leo_ast::Block { statements, span, id })
1674 }
1675
1676 fn let_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1678 debug_assert_eq!(node.kind(), LET_STMT);
1679 let span = self.to_span(node);
1680 let id = self.builder.next_id();
1681
1682 let place = match children(node).find(|n| matches!(n.kind(), IDENT_PATTERN | TUPLE_PATTERN | WILDCARD_PATTERN))
1684 {
1685 Some(pattern_node) => self.pattern_to_definition_place(&pattern_node)?,
1686 None => {
1687 self.emit_unexpected_str("pattern in let statement", node.text(), span);
1688 leo_ast::DefinitionPlace::Single(self.error_identifier(span))
1689 }
1690 };
1691
1692 let type_ = children(node).find(|n| n.kind().is_type()).map(|n| self.to_type(&n)).transpose()?;
1694
1695 let value = self.require_expression(node, "value in let statement")?;
1696
1697 Ok(leo_ast::DefinitionStatement { place, type_, value, span, id }.into())
1698 }
1699
1700 fn pattern_to_definition_place(&self, node: &SyntaxNode) -> Result<leo_ast::DefinitionPlace> {
1702 let span = self.to_span(node);
1703 match node.kind() {
1704 IDENT_PATTERN => {
1705 let ident = self.require_ident(node, "identifier in pattern");
1706 self.validate_definition_identifier(&ident);
1707 Ok(leo_ast::DefinitionPlace::Single(ident))
1708 }
1709 TUPLE_PATTERN => {
1710 let names = children(node)
1711 .filter(|n| matches!(n.kind(), IDENT_PATTERN | WILDCARD_PATTERN))
1712 .map(|n| {
1713 if n.kind() == WILDCARD_PATTERN {
1714 let span = self.to_span(&n);
1716 leo_ast::Identifier { name: Symbol::intern("_"), span, id: self.builder.next_id() }
1717 } else {
1718 let ident = self.require_ident(&n, "identifier in pattern");
1719 self.validate_definition_identifier(&ident);
1720 ident
1721 }
1722 })
1723 .collect();
1724 Ok(leo_ast::DefinitionPlace::Multiple(names))
1725 }
1726 WILDCARD_PATTERN => {
1727 let ident = leo_ast::Identifier { name: Symbol::intern("_"), span, id: self.builder.next_id() };
1728 Ok(leo_ast::DefinitionPlace::Single(ident))
1729 }
1730 _ => {
1731 self.emit_unexpected_str("valid pattern", node.text(), span);
1732 let ident = self.error_identifier(span);
1733 Ok(leo_ast::DefinitionPlace::Single(ident))
1734 }
1735 }
1736 }
1737
1738 fn const_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1740 debug_assert_eq!(node.kind(), CONST_STMT);
1741 let span = self.to_span(node);
1742 let id = self.builder.next_id();
1743
1744 let place = self.require_ident(node, "name in const declaration");
1745
1746 let type_ = self.require_type(node, "type in const declaration")?;
1747
1748 let value = self.require_expression(node, "value in const declaration")?;
1749
1750 Ok(leo_ast::ConstDeclaration { place, type_, value, span, id }.into())
1751 }
1752
1753 fn return_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1755 debug_assert_eq!(node.kind(), RETURN_STMT);
1756 let span = self.to_span(node);
1757 let id = self.builder.next_id();
1758
1759 let expression = children(node)
1761 .find(|n| n.kind().is_expression())
1762 .map(|n| self.to_expression(&n))
1763 .transpose()?
1764 .unwrap_or_else(|| leo_ast::UnitExpression { span, id: self.builder.next_id() }.into());
1765
1766 Ok(leo_ast::ReturnStatement { expression, span, id }.into())
1767 }
1768
1769 fn expr_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1771 debug_assert_eq!(node.kind(), EXPR_STMT);
1772 let span = self.to_span(node);
1773 let id = self.builder.next_id();
1774
1775 let expression = self.require_expression(node, "expression in expression statement")?;
1776
1777 Ok(leo_ast::ExpressionStatement { expression, span, id }.into())
1778 }
1779
1780 fn simple_assign_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1782 debug_assert_eq!(node.kind(), ASSIGN_STMT);
1783 let span = self.to_span(node);
1784 let id = self.builder.next_id();
1785
1786 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1787
1788 let place = match exprs.next() {
1789 Some(n) => self.to_expression(&n)?,
1790 None => {
1791 self.emit_unexpected_str("left side in assignment", node.text(), span);
1792 return Ok(leo_ast::ExpressionStatement { expression: self.error_expression(span), span, id }.into());
1793 }
1794 };
1795
1796 let value = match exprs.next() {
1797 Some(n) => self.to_expression(&n)?,
1798 None => {
1799 self.emit_unexpected_str("right side in assignment", node.text(), span);
1800 self.error_expression(span)
1801 }
1802 };
1803
1804 Ok(leo_ast::AssignStatement { place, value, span, id }.into())
1805 }
1806
1807 fn compound_assign_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1811 debug_assert_eq!(node.kind(), COMPOUND_ASSIGN_STMT);
1812 let span = self.to_span(node);
1813 let id = self.builder.next_id();
1814
1815 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1816
1817 let left = match exprs.next() {
1818 Some(n) => self.to_expression(&n)?,
1819 None => {
1820 self.emit_unexpected_str("left side in compound assignment", node.text(), span);
1821 return Ok(leo_ast::ExpressionStatement { expression: self.error_expression(span), span, id }.into());
1822 }
1823 };
1824
1825 let right = match exprs.next() {
1826 Some(n) => self.to_expression(&n)?,
1827 None => {
1828 self.emit_unexpected_str("right side in compound assignment", node.text(), span);
1829 self.error_expression(span)
1830 }
1831 };
1832
1833 let op_token =
1834 tokens(node).find(|t| is_assign_op(t.kind())).expect("COMPOUND_ASSIGN_STMT should have operator");
1835
1836 let binary_op = match op_token.kind() {
1837 PLUS_EQ => leo_ast::BinaryOperation::Add,
1838 MINUS_EQ => leo_ast::BinaryOperation::Sub,
1839 STAR_EQ => leo_ast::BinaryOperation::Mul,
1840 SLASH_EQ => leo_ast::BinaryOperation::Div,
1841 PERCENT_EQ => leo_ast::BinaryOperation::Rem,
1842 STAR2_EQ => leo_ast::BinaryOperation::Pow,
1843 AMP_EQ => leo_ast::BinaryOperation::BitwiseAnd,
1844 PIPE_EQ => leo_ast::BinaryOperation::BitwiseOr,
1845 CARET_EQ => leo_ast::BinaryOperation::Xor,
1846 SHL_EQ => leo_ast::BinaryOperation::Shl,
1847 SHR_EQ => leo_ast::BinaryOperation::Shr,
1848 AMP2_EQ => leo_ast::BinaryOperation::And,
1849 PIPE2_EQ => leo_ast::BinaryOperation::Or,
1850 k => panic!("unexpected compound assignment operator: {k:?}"),
1851 };
1852
1853 let value =
1854 leo_ast::BinaryExpression { left: left.clone(), right, op: binary_op, span, id: self.builder.next_id() }
1855 .into();
1856
1857 Ok(leo_ast::AssignStatement { place: left, value, span, id }.into())
1858 }
1859
1860 fn if_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1862 debug_assert_eq!(node.kind(), IF_STMT);
1863 let span = self.to_span(node);
1864 let id = self.builder.next_id();
1865
1866 let condition = self.require_expression(node, "condition in if statement")?;
1867
1868 let mut block_or_if = children(node).filter(|n| n.kind() == BLOCK || n.kind() == IF_STMT);
1871
1872 let then = match block_or_if.next() {
1873 Some(n) if n.kind() == BLOCK => self.to_block(&n)?,
1874 _ => {
1875 self.emit_unexpected_str("then block in if statement", node.text(), span);
1876 self.error_block(span)
1877 }
1878 };
1879
1880 let otherwise = block_or_if.next().map(|n| self.to_statement(&n)).transpose()?.map(Box::new);
1881
1882 Ok(leo_ast::ConditionalStatement { condition, then, otherwise, span, id }.into())
1883 }
1884
1885 fn for_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1887 debug_assert!(matches!(node.kind(), FOR_STMT | FOR_INCLUSIVE_STMT));
1888 let span = self.to_span(node);
1889 let id = self.builder.next_id();
1890
1891 let variable = self.require_ident(node, "variable in for statement");
1892
1893 let type_ = children(node).find(|n| n.kind().is_type()).map(|n| self.to_type(&n)).transpose()?;
1895
1896 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1898
1899 let start = match exprs.next() {
1900 Some(n) => self.to_expression(&n)?,
1901 None => {
1902 self.emit_unexpected_str("start expression in for statement", node.text(), span);
1903 self.error_expression(span)
1904 }
1905 };
1906
1907 let stop = match exprs.next() {
1908 Some(n) => self.to_expression(&n)?,
1909 None => {
1910 self.emit_unexpected_str("stop expression in for statement", node.text(), span);
1911 self.error_expression(span)
1912 }
1913 };
1914
1915 let block = match children(node).find(|n| n.kind() == BLOCK) {
1917 Some(block_node) => self.to_block(&block_node)?,
1918 None => {
1919 self.emit_unexpected_str("block in for statement", node.text(), span);
1920 self.error_block(span)
1921 }
1922 };
1923
1924 let inclusive = node.kind() == FOR_INCLUSIVE_STMT;
1925
1926 Ok(leo_ast::IterationStatement { variable, type_, start, stop, inclusive, block, span, id }.into())
1927 }
1928
1929 fn collect_program_item(
1935 &self,
1936 item: &SyntaxNode,
1937 is_in_program_block: bool,
1938 functions: &mut Vec<(Symbol, leo_ast::Function)>,
1939 composites: &mut Vec<(Symbol, leo_ast::Composite)>,
1940 consts: &mut Vec<(Symbol, leo_ast::ConstDeclaration)>,
1941 interfaces: &mut Vec<(Symbol, leo_ast::Interface)>,
1942 ) -> Result<()> {
1943 match item.kind() {
1944 FUNCTION_DEF | FINAL_FN_DEF => {
1945 let func = self.to_function(item, is_in_program_block)?;
1946 functions.push((func.identifier.name, func));
1947 }
1948 STRUCT_DEF | RECORD_DEF => {
1949 let composite = self.to_composite(item)?;
1950 composites.push((composite.identifier.name, composite));
1951 }
1952 GLOBAL_CONST => {
1953 let global_const = self.to_global_const(item)?;
1954 consts.push((global_const.place.name, global_const));
1955 }
1956 INTERFACE_DEF => {
1957 let interface = self.to_interface(item)?;
1958 interfaces.push((interface.identifier.name, interface));
1959 }
1960 _ => {}
1961 }
1962 Ok(())
1963 }
1964
1965 fn collect_library_item(
1967 &self,
1968 item: &SyntaxNode,
1969 consts: &mut Vec<(Symbol, leo_ast::ConstDeclaration)>,
1970 structs: &mut Vec<(Symbol, leo_ast::Composite)>,
1971 functions: &mut Vec<(Symbol, leo_ast::Function)>,
1972 interfaces: &mut Vec<(Symbol, leo_ast::Interface)>,
1973 ) -> Result<()> {
1974 if is_library_item(item.kind()) {
1975 match item.kind() {
1976 GLOBAL_CONST => {
1977 let global_const = self.to_global_const(item)?;
1978 consts.push((global_const.place.name, global_const));
1979 }
1980 STRUCT_DEF => {
1981 let composite = self.to_composite(item)?;
1982 structs.push((composite.identifier.name, composite));
1983 }
1984 FUNCTION_DEF => {
1985 let func = self.to_function(item, false)?;
1987 functions.push((func.identifier.name, func));
1988 }
1989 INTERFACE_DEF => {
1990 let interface = self.to_interface(item)?;
1991 interfaces.push((interface.identifier.name, interface));
1992 }
1993 _ => {}
1994 }
1995 } else if is_program_item(item.kind()) {
1996 let span = self.to_span(item);
1998 self.handler.emit_err(ParserError::custom(
1999 "Only `const` declarations, `struct` definitions, `fn` functions, and `interface` definitions are allowed in a library.",
2000 span,
2001 ));
2002 }
2003 Ok(())
2006 }
2007
2008 fn to_module(&self, node: &SyntaxNode, program_name: Symbol, path: Vec<Symbol>) -> Result<leo_ast::Module> {
2010 let mut functions = Vec::new();
2012 let mut composites = Vec::new();
2013 let mut consts = Vec::new();
2014 let mut interfaces = Vec::new();
2015
2016 for child in children(node) {
2017 if child.kind() == PROGRAM_DECL {
2018 for item in children(&child) {
2019 self.collect_program_item(
2020 &item,
2021 true,
2022 &mut functions,
2023 &mut composites,
2024 &mut consts,
2025 &mut interfaces,
2026 )?;
2027 }
2028 } else {
2029 self.collect_program_item(
2030 &child,
2031 false,
2032 &mut functions,
2033 &mut composites,
2034 &mut consts,
2035 &mut interfaces,
2036 )?;
2037 }
2038 }
2039
2040 functions.sort_by_key(|func| if func.1.variant.is_entry() { 0u8 } else { 1u8 });
2042
2043 Ok(leo_ast::Module { program_name, path, consts, composites, functions, interfaces })
2044 }
2045
2046 fn to_main(&self, node: &SyntaxNode) -> Result<leo_ast::Program> {
2048 let mut imports = indexmap::IndexMap::new();
2050 let mut functions = Vec::new();
2051 let mut composites = Vec::new();
2052 let mut consts = Vec::new();
2053 let mut mappings = Vec::new();
2054 let mut storage_variables = Vec::new();
2055 let mut constructors = Vec::new();
2056 let mut interfaces = Vec::new();
2057 let mut program_name = None;
2058 let mut network = None;
2059 let mut parents = Vec::new();
2060 let mut span = None;
2061
2062 for child in children(node) {
2063 match child.kind() {
2064 IMPORT => {
2065 let program_id = self.import_to_program_id(&child)?;
2066 imports.insert(program_id.as_symbol(), program_id);
2067 }
2068 PROGRAM_DECL => {
2069 if program_name.is_some() {
2070 self.handler.emit_err(ParserError::multiple_program_declarations(self.non_trivia_span(&child)));
2071 continue;
2072 }
2073 let (pname, pnetwork, pparents) = self.program_decl_to_name_with_parent(&child)?;
2075 program_name = Some(pname);
2076 network = Some(pnetwork);
2077 parents = pparents;
2078 span = Some(self.to_span(&child));
2079
2080 for item in children(&child) {
2082 self.collect_program_item(
2083 &item,
2084 true,
2085 &mut functions,
2086 &mut composites,
2087 &mut consts,
2088 &mut interfaces,
2089 )?;
2090 match item.kind() {
2091 MAPPING_DEF => {
2092 let mapping = self.to_mapping(&item)?;
2093 mappings.push((mapping.identifier.name, mapping));
2094 }
2095 STORAGE_DEF => {
2096 let storage = self.to_storage(&item)?;
2097 storage_variables.push((storage.identifier.name, storage));
2098 }
2099 CONSTRUCTOR_DEF => {
2100 constructors.push(self.to_constructor(&item)?);
2101 }
2102 _ => {}
2103 }
2104 }
2105 }
2106 _ => {
2107 self.collect_program_item(
2108 &child,
2109 false,
2110 &mut functions,
2111 &mut composites,
2112 &mut consts,
2113 &mut interfaces,
2114 )?;
2115 }
2116 }
2117 }
2118
2119 if let Some(extra) = constructors.get(1) {
2120 return Err(ParserError::custom("A program can only have one constructor.", extra.span).into());
2121 }
2122
2123 let (Some(program_name), Some(network), Some(span)) = (program_name, network, span) else {
2124 return Err(ParserError::missing_program_scope(self.to_span(node)).into());
2125 };
2126
2127 functions.sort_by_key(|func| if func.1.variant.is_entry() { 0u8 } else { 1u8 });
2129
2130 let program_id = leo_ast::ProgramId { name: program_name, network };
2131 let program_id_as_symbol = program_id.as_symbol();
2132 let program_scope = leo_ast::ProgramScope {
2133 program_id,
2134 parents,
2135 consts,
2136 composites,
2137 mappings,
2138 storage_variables,
2139 functions,
2140 interfaces,
2141 constructor: constructors.pop(),
2142 span,
2143 };
2144
2145 Ok(leo_ast::Program {
2146 imports,
2147 modules: indexmap::IndexMap::new(),
2148 stubs: indexmap::IndexMap::new(),
2149 program_scopes: vec![(program_id_as_symbol, program_scope)].into_iter().collect(),
2150 })
2151 }
2152
2153 fn to_library(&self, name: Symbol, node: &SyntaxNode) -> Result<leo_ast::Library> {
2155 let mut consts = Vec::new();
2156 let mut structs = Vec::new();
2157 let mut functions = Vec::new();
2158 let mut interfaces = Vec::new();
2159
2160 for child in children(node) {
2161 self.collect_library_item(&child, &mut consts, &mut structs, &mut functions, &mut interfaces)?;
2162 }
2163
2164 Ok(leo_ast::Library { name, modules: indexmap::IndexMap::new(), consts, structs, functions, interfaces })
2165 }
2166
2167 fn import_to_program_id(&self, node: &SyntaxNode) -> Result<leo_ast::ProgramId> {
2169 debug_assert_eq!(node.kind(), IMPORT);
2170 let span = self.to_span(node);
2171
2172 let program_name_text = match tokens(node).find(|t| t.kind() == IDENT) {
2174 Some(name_token) => name_token.text().to_string(),
2175 None => {
2176 self.emit_unexpected_str("import name", node.text(), span);
2177 "_error".to_string()
2178 }
2179 };
2180
2181 let network_span = tokens(node).find(|t| t.kind() == KW_ALEO).map(|t| self.token_span(&t)).unwrap_or(span); let program_id = leo_ast::ProgramId {
2185 name: leo_ast::Identifier { name: Symbol::intern(&program_name_text), span, id: self.builder.next_id() },
2186 network: leo_ast::Identifier {
2187 name: Symbol::intern("aleo"),
2188 span: network_span,
2189 id: self.builder.next_id(),
2190 },
2191 };
2192
2193 if tokens(node).all(|t| t.kind() != KW_ALEO)
2195 && let Some(net_token) = find_invalid_network(node)
2196 {
2197 self.handler.emit_err(ParserError::invalid_network(self.token_span(&net_token)));
2198 }
2199
2200 Ok(program_id)
2201 }
2202
2203 fn program_decl_to_name(&self, node: &SyntaxNode) -> Result<(leo_ast::Identifier, leo_ast::Identifier)> {
2205 debug_assert_eq!(node.kind(), PROGRAM_DECL);
2206 let span = self.to_span(node);
2207
2208 let program_name = self.require_ident(node, "program name");
2210
2211 let network = match tokens(node).find(|t| t.kind() == KW_ALEO) {
2212 Some(aleo_token) => leo_ast::Identifier {
2213 name: Symbol::intern("aleo"),
2214 span: self.token_span(&aleo_token),
2215 id: self.builder.next_id(),
2216 },
2217 None => {
2218 if let Some(net_token) = find_invalid_network(node) {
2220 self.handler.emit_err(ParserError::invalid_network(self.token_span(&net_token)));
2221 } else {
2222 self.emit_unexpected_str(".aleo network", node.text(), span);
2223 }
2224 leo_ast::Identifier { name: Symbol::intern("aleo"), span, id: self.builder.next_id() }
2225 }
2226 };
2227
2228 Ok((program_name, network))
2229 }
2230
2231 fn program_decl_to_name_with_parent(
2233 &self,
2234 node: &SyntaxNode,
2235 ) -> Result<(leo_ast::Identifier, leo_ast::Identifier, Parents)> {
2236 debug_assert_eq!(node.kind(), PROGRAM_DECL);
2237 let (program_name, network) = self.program_decl_to_name(node)?;
2238
2239 let parents = if let Some(parent_list) = children(node).find(|n| n.kind() == PARENT_LIST) {
2240 self.collect_parent_list(&parent_list)?
2241 } else {
2242 vec![]
2243 };
2244
2245 Ok((program_name, network, parents))
2246 }
2247
2248 fn collect_parent_list(&self, node: &SyntaxNode) -> Result<Parents> {
2249 debug_assert_eq!(node.kind(), PARENT_LIST);
2250 children(node)
2251 .filter(|n| n.kind().is_type())
2252 .map(|n| self.to_type(&n).map(|t| (self.to_span(&n), t)))
2253 .collect::<Result<Vec<_>>>()
2254 }
2255
2256 fn collect_annotations(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::Annotation>> {
2258 children(node).filter(|n| n.kind() == ANNOTATION).map(|n| self.to_annotation(&n)).collect()
2259 }
2260
2261 fn require_block(&self, node: &SyntaxNode, span: Span) -> Result<leo_ast::Block> {
2263 Ok(children(node)
2264 .find(|n| n.kind() == BLOCK)
2265 .map(|n| self.to_block(&n))
2266 .transpose()?
2267 .unwrap_or_else(|| self.error_block(span)))
2268 }
2269
2270 fn to_function(&self, node: &SyntaxNode, is_in_program_block: bool) -> Result<leo_ast::Function> {
2272 debug_assert!(matches!(node.kind(), FUNCTION_DEF | FINAL_FN_DEF | CONSTRUCTOR_DEF));
2273 let span = self.span_including_annotations(node, self.non_trivia_span(node));
2274 let id = self.builder.next_id();
2275
2276 let annotations = self.collect_annotations(node)?;
2277
2278 let variant = if is_in_program_block {
2280 leo_ast::Variant::EntryPoint
2281 } else {
2282 match node.kind() {
2283 FINAL_FN_DEF => leo_ast::Variant::FinalFn,
2284 _ => leo_ast::Variant::Fn,
2285 }
2286 };
2287
2288 let identifier = self.require_ident(node, "function name");
2289 self.validate_identifier(&identifier);
2290
2291 let const_parameters = self.extract_const_parameters(node)?;
2292
2293 let input = children(node)
2295 .find(|n| n.kind() == PARAM_LIST)
2296 .map(|n| self.param_list_to_inputs(&n))
2297 .transpose()?
2298 .unwrap_or_default();
2299
2300 let (output, output_type) = if let Some(return_type_node) = children(node).find(|n| n.kind() == RETURN_TYPE) {
2306 self.return_type_to_outputs(&return_type_node)?
2308 } else if let Some(type_node) = children(node).find(|n| n.kind().is_type()) {
2309 let type_ = self.to_type(&type_node)?;
2311 let (mode, mode_start) = self.return_mode_before(node, &type_node);
2313 let type_span = self.content_span(&type_node);
2314 let output_span = match mode_start {
2315 Some(start) => Span::new(start, type_span.hi),
2316 None => type_span,
2317 };
2318 let output =
2319 vec![leo_ast::Output { mode, type_: type_.clone(), span: output_span, id: self.builder.next_id() }];
2320 (output, type_)
2321 } else {
2322 (Vec::new(), leo_ast::Type::Unit)
2323 };
2324
2325 let block = self.require_block(node, span)?;
2326
2327 Ok(leo_ast::Function {
2328 annotations,
2329 variant,
2330 identifier,
2331 const_parameters,
2332 input,
2333 output,
2334 output_type,
2335 block,
2336 span,
2337 id,
2338 })
2339 }
2340
2341 fn return_mode_before(&self, parent: &SyntaxNode, type_node: &SyntaxNode) -> (leo_ast::Mode, Option<u32>) {
2347 let type_start = type_node.text_range().start();
2348 let mut mode = leo_ast::Mode::None;
2349 let mut mode_start = None;
2350 for token in tokens(parent) {
2351 let token_end = token.text_range().end();
2352 if token_end > type_start {
2353 break;
2354 }
2355 if let Some(m) = token_kind_to_mode(token.kind()) {
2356 mode = m;
2357 mode_start = Some(u32::from(token.text_range().start()) + self.start_pos);
2358 }
2359 }
2360 (mode, mode_start)
2361 }
2362
2363 fn return_type_to_outputs(&self, node: &SyntaxNode) -> Result<(Vec<leo_ast::Output>, leo_ast::Type)> {
2365 debug_assert_eq!(node.kind(), RETURN_TYPE);
2366
2367 let mut outputs = Vec::new();
2370 let mut current_mode = leo_ast::Mode::None;
2371 let mut current_mode_start: Option<u32> = None;
2372
2373 for child in node.children_with_tokens() {
2374 match &child {
2375 SyntaxElement::Token(token) if !token.kind().is_trivia() => {
2376 if let Some(m) = token_kind_to_mode(token.kind()) {
2377 current_mode = m;
2378 current_mode_start = Some(u32::from(token.text_range().start()) + self.start_pos);
2379 }
2380 }
2381 SyntaxElement::Node(child_node) if child_node.kind().is_type() => {
2382 let type_ = self.to_type(child_node)?;
2383 let type_span = self.content_span(child_node);
2384 let output_span = match current_mode_start.take() {
2385 Some(start) => Span::new(start, type_span.hi),
2386 None => type_span,
2387 };
2388 outputs.push(leo_ast::Output {
2389 mode: current_mode,
2390 type_,
2391 span: output_span,
2392 id: self.builder.next_id(),
2393 });
2394 current_mode = leo_ast::Mode::None;
2395 }
2396 _ => {}
2397 }
2398 }
2399
2400 let output_type = match outputs.len() {
2401 0 => leo_ast::Type::Unit,
2402 1 => outputs[0].type_.clone(),
2403 _ => leo_ast::TupleType::new(outputs.iter().map(|o| o.type_.clone()).collect()).into(),
2404 };
2405
2406 Ok((outputs, output_type))
2407 }
2408
2409 fn to_annotation(&self, node: &SyntaxNode) -> Result<leo_ast::Annotation> {
2411 debug_assert_eq!(node.kind(), ANNOTATION);
2412 let span = self.trimmed_span(node);
2413 let id = self.builder.next_id();
2414
2415 let identifier = match tokens(node).find(|t| t.kind() == IDENT || t.kind().is_keyword()) {
2418 Some(name_token) => {
2419 let name = Symbol::intern(name_token.text());
2420 let name_span = self.token_span(&name_token);
2421 leo_ast::Identifier { name, span: name_span, id: self.builder.next_id() }
2422 }
2423 None => {
2424 self.emit_unexpected_str("annotation name", node.text(), span);
2425 self.error_identifier(span)
2426 }
2427 };
2428
2429 let map = children(node)
2431 .filter(|n| n.kind() == ANNOTATION_PAIR)
2432 .filter_map(|pair| {
2433 let key =
2434 tokens(&pair).find(|t| t.kind() == IDENT || t.kind() == KW_ADDRESS || t.kind() == KW_MAPPING)?;
2435 let val = tokens(&pair).find(|t| t.kind() == STRING)?;
2436 let text = val.text();
2437 Some((Symbol::intern(key.text()), text[1..text.len() - 1].to_string()))
2438 })
2439 .collect();
2440
2441 Ok(leo_ast::Annotation { identifier, map, span, id })
2442 }
2443
2444 fn param_list_to_inputs(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::Input>> {
2446 debug_assert_eq!(node.kind(), PARAM_LIST);
2447
2448 children(node)
2449 .filter(|n| matches!(n.kind(), PARAM | PARAM_PUBLIC | PARAM_PRIVATE | PARAM_CONSTANT))
2450 .map(|n| self.param_to_input(&n))
2451 .collect()
2452 }
2453
2454 fn param_to_input(&self, node: &SyntaxNode) -> Result<leo_ast::Input> {
2456 debug_assert!(matches!(node.kind(), PARAM | PARAM_PUBLIC | PARAM_PRIVATE | PARAM_CONSTANT));
2457 let span = self.non_trivia_span(node);
2458 let id = self.builder.next_id();
2459
2460 let mode = node_kind_to_mode(node.kind());
2461
2462 let identifier = self.require_ident(node, "parameter name");
2463 self.validate_identifier(&identifier);
2464
2465 let type_ = self.require_type(node, "parameter type")?;
2466
2467 Ok(leo_ast::Input { identifier, mode, type_, span, id })
2468 }
2469
2470 fn to_const_parameters(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::ConstParameter>> {
2472 debug_assert_eq!(node.kind(), CONST_PARAM_LIST);
2473
2474 children(node)
2475 .filter(|n| n.kind() == CONST_PARAM)
2476 .map(|n| {
2477 let span = self.non_trivia_span(&n);
2478 let id = self.builder.next_id();
2479
2480 let identifier = self.require_ident(&n, "const parameter name");
2481
2482 let type_ = self.require_type(&n, "const parameter type")?;
2483
2484 Ok(leo_ast::ConstParameter { identifier, type_, span, id })
2485 })
2486 .collect()
2487 }
2488
2489 fn extract_const_parameters(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::ConstParameter>> {
2491 children(node)
2492 .find(|n| n.kind() == CONST_PARAM_LIST)
2493 .map(|n| self.to_const_parameters(&n))
2494 .transpose()
2495 .map(|opt| opt.unwrap_or_default())
2496 }
2497
2498 fn to_composite(&self, node: &SyntaxNode) -> Result<leo_ast::Composite> {
2500 debug_assert!(matches!(node.kind(), STRUCT_DEF | RECORD_DEF));
2501 let span = self.non_trivia_span(node);
2502 let id = self.builder.next_id();
2503
2504 let is_record = node.kind() == RECORD_DEF;
2505
2506 let identifier = self.require_ident(node, "struct/record name");
2507 self.validate_identifier(&identifier);
2508
2509 let const_parameters = self.extract_const_parameters(node)?;
2510
2511 let members = children(node)
2513 .filter(|n| {
2514 matches!(
2515 n.kind(),
2516 STRUCT_MEMBER | STRUCT_MEMBER_PUBLIC | STRUCT_MEMBER_PRIVATE | STRUCT_MEMBER_CONSTANT
2517 )
2518 })
2519 .map(|n| self.struct_member_to_member(&n))
2520 .collect::<Result<Vec<_>>>()?;
2521
2522 Ok(leo_ast::Composite { identifier, const_parameters, members, is_record, span, id })
2523 }
2524
2525 fn struct_member_to_member(&self, node: &SyntaxNode) -> Result<leo_ast::Member> {
2527 debug_assert!(matches!(
2528 node.kind(),
2529 STRUCT_MEMBER | STRUCT_MEMBER_PUBLIC | STRUCT_MEMBER_PRIVATE | STRUCT_MEMBER_CONSTANT
2530 ));
2531 let span = self.non_trivia_span(node);
2532 let id = self.builder.next_id();
2533
2534 let mode = node_kind_to_mode(node.kind());
2535
2536 let identifier = self.require_ident(node, "member name");
2537 self.validate_identifier(&identifier);
2538
2539 let type_ = self.require_type(node, "member type")?;
2540
2541 Ok(leo_ast::Member { mode, identifier, type_, span, id })
2542 }
2543
2544 fn to_global_const(&self, node: &SyntaxNode) -> Result<leo_ast::ConstDeclaration> {
2546 debug_assert_eq!(node.kind(), GLOBAL_CONST);
2547 let span = self.non_trivia_span(node);
2548 let id = self.builder.next_id();
2549
2550 let place = self.require_ident(node, "const name");
2551 self.validate_definition_identifier(&place);
2552
2553 let type_ = self.require_type(node, "const type")?;
2554
2555 let value = self.require_expression(node, "const value")?;
2556
2557 Ok(leo_ast::ConstDeclaration { place, type_, value, span, id })
2558 }
2559
2560 fn parse_mapping_def(
2562 &self,
2563 node: &SyntaxNode,
2564 ) -> Result<(leo_ast::Identifier, leo_ast::Type, leo_ast::Type, Span, NodeID)> {
2565 debug_assert_eq!(node.kind(), MAPPING_DEF);
2566 let span = self.non_trivia_span(node);
2567 let id = self.builder.next_id();
2568 let identifier = self.require_ident(node, "name in mapping");
2569 let mut type_nodes = children(node).filter(|n| n.kind().is_type());
2570 let key_type = match type_nodes.next() {
2571 Some(key_node) => self.to_type(&key_node)?,
2572 None => {
2573 self.emit_unexpected_str("key type in mapping", node.text(), span);
2574 leo_ast::Type::Err
2575 }
2576 };
2577 let value_type = match type_nodes.next() {
2578 Some(value_node) => self.to_type(&value_node)?,
2579 None => {
2580 self.emit_unexpected_str("value type in mapping", node.text(), span);
2581 leo_ast::Type::Err
2582 }
2583 };
2584 Ok((identifier, key_type, value_type, span, id))
2585 }
2586
2587 fn to_mapping(&self, node: &SyntaxNode) -> Result<leo_ast::Mapping> {
2589 let (identifier, key_type, value_type, span, id) = self.parse_mapping_def(node)?;
2590 Ok(leo_ast::Mapping { identifier, key_type, value_type, span, id })
2591 }
2592
2593 fn to_mapping_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::MappingPrototype> {
2595 let (identifier, key_type, value_type, span, id) = self.parse_mapping_def(node)?;
2596 Ok(leo_ast::MappingPrototype { identifier, key_type, value_type, span, id })
2597 }
2598
2599 fn parse_storage_def(&self, node: &SyntaxNode) -> Result<(leo_ast::Identifier, leo_ast::Type, Span, NodeID)> {
2601 debug_assert_eq!(node.kind(), STORAGE_DEF);
2602 let span = self.non_trivia_span(node);
2603 let id = self.builder.next_id();
2604 let identifier = self.require_ident(node, "name in storage");
2605 let type_ = self.require_type(node, "type in storage")?;
2606 Ok((identifier, type_, span, id))
2607 }
2608
2609 fn to_storage(&self, node: &SyntaxNode) -> Result<leo_ast::StorageVariable> {
2611 let (identifier, type_, span, id) = self.parse_storage_def(node)?;
2612 Ok(leo_ast::StorageVariable { identifier, type_, span, id })
2613 }
2614
2615 fn to_storage_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::StorageVariablePrototype> {
2617 let (identifier, type_, span, id) = self.parse_storage_def(node)?;
2618 Ok(leo_ast::StorageVariablePrototype { identifier, type_, span, id })
2619 }
2620
2621 fn to_constructor(&self, node: &SyntaxNode) -> Result<leo_ast::Constructor> {
2623 debug_assert_eq!(node.kind(), CONSTRUCTOR_DEF);
2624 let span = self.span_including_annotations(node, self.non_trivia_span(node));
2625 let id = self.builder.next_id();
2626
2627 let annotations = self.collect_annotations(node)?;
2628 let block = self.require_block(node, span)?;
2629
2630 Ok(leo_ast::Constructor { annotations, block, span, id })
2631 }
2632
2633 fn to_interface(&self, node: &SyntaxNode) -> Result<leo_ast::Interface> {
2639 debug_assert_eq!(node.kind(), INTERFACE_DEF);
2640 let span = self.to_span(node);
2641
2642 let identifier = self.require_ident(node, "interface name");
2644
2645 let parents = if let Some(parent_list) = children(node).find(|n| n.kind() == PARENT_LIST) {
2648 self.collect_parent_list(&parent_list)?
2649 } else {
2650 vec![]
2651 };
2652
2653 let mut functions = Vec::new();
2654 let mut records = Vec::new();
2655 let mut mappings = Vec::new();
2656 let mut storages = Vec::new();
2657
2658 for child in children(node) {
2659 match child.kind() {
2660 FN_PROTOTYPE_DEF => {
2661 let proto = self.to_function_prototype(&child)?;
2662 functions.push((proto.identifier.name, proto));
2663 }
2664 RECORD_PROTOTYPE_DEF => {
2665 let proto = self.to_record_prototype(&child)?;
2666 records.push((proto.identifier.name, proto));
2667 }
2668 MAPPING_DEF => {
2669 let mapping = self.to_mapping_prototype(&child)?;
2670 mappings.push(mapping);
2671 }
2672 STORAGE_DEF => {
2673 let storage = self.to_storage_prototype(&child)?;
2674 storages.push(storage);
2675 }
2676 _ => {}
2677 }
2678 }
2679
2680 Ok(leo_ast::Interface {
2681 identifier,
2682 parents,
2683 span,
2684 id: self.builder.next_id(),
2685 functions,
2686 records,
2687 mappings,
2688 storages,
2689 })
2690 }
2691
2692 fn to_function_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::FunctionPrototype> {
2694 debug_assert_eq!(node.kind(), FN_PROTOTYPE_DEF);
2695 let span = self.to_span(node);
2696
2697 let identifier = self.require_ident(node, "function name");
2698
2699 let const_parameters = self.extract_const_parameters(node)?;
2701
2702 let input = children(node)
2704 .find(|n| n.kind() == PARAM_LIST)
2705 .map(|n| self.param_list_to_inputs(&n))
2706 .transpose()?
2707 .unwrap_or_default();
2708
2709 let output = if let Some(return_type_node) = children(node).find(|n| n.kind() == RETURN_TYPE) {
2712 self.return_type_to_outputs(&return_type_node)?.0
2714 } else if let Some(type_node) = children(node).find(|n| n.kind().is_type()) {
2715 let type_ = self.to_type(&type_node)?;
2717 let (mode, mode_start) = self.return_mode_before(node, &type_node);
2719 let type_span = self.content_span(&type_node);
2720 let output_span = match mode_start {
2721 Some(start) => Span::new(start, type_span.hi),
2722 None => type_span,
2723 };
2724 vec![leo_ast::Output { mode, type_, span: output_span, id: self.builder.next_id() }]
2725 } else {
2726 Vec::new()
2727 };
2728
2729 Ok(leo_ast::FunctionPrototype::new(
2730 vec![], identifier,
2732 const_parameters,
2733 input,
2734 output,
2735 span,
2736 self.builder.next_id(),
2737 ))
2738 }
2739
2740 fn to_record_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::RecordPrototype> {
2742 debug_assert_eq!(node.kind(), RECORD_PROTOTYPE_DEF);
2743
2744 let span = self.to_span(node);
2745 let identifier = self.require_ident(node, "record name");
2746 let members = children(node)
2747 .filter(|n| {
2748 matches!(
2749 n.kind(),
2750 STRUCT_MEMBER | STRUCT_MEMBER_PUBLIC | STRUCT_MEMBER_PRIVATE | STRUCT_MEMBER_CONSTANT
2751 )
2752 })
2753 .map(|n| self.struct_member_to_member(&n))
2754 .collect::<Result<Vec<_>>>()?;
2755
2756 let is_redundant = members.is_empty()
2758 || members.iter().all(|m| {
2759 m.identifier.name == sym::owner && m.type_ == leo_ast::Type::Address && m.mode == leo_ast::Mode::None
2760 });
2761 if is_redundant && !members.is_empty() {
2762 self.handler.emit_warning(ParserWarning::record_prototype_redundant(identifier.name, span));
2764 return Ok(leo_ast::RecordPrototype { identifier, span, members: Vec::new(), id: self.builder.next_id() });
2765 } else if is_redundant {
2766 let had_braces = node.children_with_tokens().any(|c| c.kind() == L_BRACE);
2769 if had_braces {
2770 self.handler.emit_warning(ParserWarning::record_prototype_redundant(identifier.name, span));
2771 }
2772 }
2773
2774 Ok(leo_ast::RecordPrototype { identifier, span, members, id: self.builder.next_id() })
2775 }
2776}
2777
2778fn clamped_span(range: TextRange, start_pos: u32, source_len: u32) -> Span {
2784 let end = start_pos + source_len;
2785 let lo = (u32::from(range.start()) + start_pos).min(end);
2786 let hi = (u32::from(range.end()) + start_pos).min(end).max(lo);
2787 Span::new(lo, hi)
2788}
2789
2790fn emit_lex_errors(handler: &Handler, lex_errors: &[leo_parser_rowan::LexError], start_pos: u32, source_len: u32) {
2792 use leo_parser_rowan::LexErrorKind;
2793 for error in lex_errors {
2794 let span = clamped_span(error.range, start_pos, source_len);
2795
2796 match &error.kind {
2797 LexErrorKind::InvalidDigit { digit, radix, token } => {
2798 handler.emit_err(ParserError::wrong_digit_for_radix_span(*digit, *radix, token, span));
2799 }
2800 LexErrorKind::CouldNotLex { content } => {
2801 handler.emit_err(ParserError::could_not_lex_span(content, span));
2802 }
2803 LexErrorKind::BidiOverride => {
2804 handler.emit_err(ParserError::lexer_bidi_override_span(span));
2805 }
2806 }
2807 }
2808}
2809
2810fn emit_parse_errors(
2813 handler: &Handler,
2814 errors: &[leo_parser_rowan::ParseError],
2815 start_pos: u32,
2816 source_len: u32,
2817 lex_errors: &[leo_parser_rowan::LexError],
2818) {
2819 use std::collections::HashSet;
2820
2821 let has_lex_errors = !lex_errors.is_empty();
2822
2823 let lex_ranges: Vec<(u32, u32)> = lex_errors
2825 .iter()
2826 .map(|e| {
2827 let lo = u32::from(e.range.start()).saturating_add(start_pos);
2828 let hi = u32::from(e.range.end()).saturating_add(start_pos);
2829 (lo, hi)
2830 })
2831 .collect();
2832
2833 let mut emitted_ranges: HashSet<(u32, u32)> = HashSet::new();
2835 let mut count = 0;
2836 let max_errors = 10;
2837
2838 for error in errors {
2839 if count >= max_errors {
2840 break;
2841 }
2842
2843 let span = clamped_span(error.range, start_pos, source_len);
2844 let range_key = (span.lo, span.hi);
2845
2846 if emitted_ranges.contains(&range_key) {
2848 continue;
2849 }
2850
2851 if has_lex_errors && span.lo == span.hi && span.hi == start_pos + source_len {
2854 continue;
2855 }
2856
2857 if lex_ranges.iter().any(|&(lo, hi)| span.lo < hi && span.hi > lo) {
2860 continue;
2861 }
2862
2863 emitted_ranges.insert(range_key);
2864
2865 let is_eof_error = match &error.found {
2868 Some(f) => f.is_empty() || f == "end of file",
2869 None => false,
2870 } || (span.lo == span.hi && span.hi >= start_pos + source_len);
2871
2872 if is_eof_error {
2873 handler.emit_err(ParserError::unexpected_eof(span));
2874 count += 1;
2875 continue;
2876 }
2877
2878 if let Some(found) = &error.found {
2880 if error.expected.is_empty() {
2881 handler.emit_err(ParserError::custom(&error.message, span));
2884 } else {
2885 let expected_str = error.expected.join(", ");
2886 handler.emit_err(ParserError::unexpected(found, expected_str, span));
2887 }
2888 count += 1;
2889 continue;
2890 }
2891
2892 handler.emit_err(ParserError::custom(&error.message, span));
2894 count += 1;
2895 }
2896}
2897
2898fn conversion_context<'a>(
2900 handler: &'a Handler,
2901 node_builder: &'a NodeBuilder,
2902 lex_errors: &[leo_parser_rowan::LexError],
2903 parse_errors: &[leo_parser_rowan::ParseError],
2904 start_pos: u32,
2905 source_len: u32,
2906) -> ConversionContext<'a> {
2907 emit_lex_errors(handler, lex_errors, start_pos, source_len);
2908 emit_parse_errors(handler, parse_errors, start_pos, source_len, lex_errors);
2909 let has_errors = !parse_errors.is_empty() || !lex_errors.is_empty();
2910 ConversionContext::new(handler, node_builder, start_pos, has_errors)
2911}
2912
2913pub fn parse_expression(
2915 handler: Handler,
2916 node_builder: &NodeBuilder,
2917 source: &str,
2918 start_pos: u32,
2919 _network: NetworkName,
2920) -> Result<leo_ast::Expression> {
2921 let parse = leo_parser_rowan::parse_expression_entry(source);
2922 let ctx =
2923 conversion_context(&handler, node_builder, parse.lex_errors(), parse.errors(), start_pos, source.len() as u32);
2924 ctx.to_expression(&parse.syntax())
2925}
2926
2927pub fn parse_statement(
2929 handler: Handler,
2930 node_builder: &NodeBuilder,
2931 source: &str,
2932 start_pos: u32,
2933 _network: NetworkName,
2934) -> Result<leo_ast::Statement> {
2935 let parse = leo_parser_rowan::parse_statement_entry(source);
2936 let ctx =
2937 conversion_context(&handler, node_builder, parse.lex_errors(), parse.errors(), start_pos, source.len() as u32);
2938 ctx.to_statement(&parse.syntax())
2939}
2940
2941pub fn parse_module(
2943 handler: Handler,
2944 node_builder: &NodeBuilder,
2945 source: &str,
2946 start_pos: u32,
2947 program_name: Symbol,
2948 path: Vec<Symbol>,
2949 _network: NetworkName,
2950) -> Result<leo_ast::Module> {
2951 let parse = leo_parser_rowan::parse_module_entry(source);
2952 let ctx =
2953 conversion_context(&handler, node_builder, parse.lex_errors(), parse.errors(), start_pos, source.len() as u32);
2954 ctx.to_module(&parse.syntax(), program_name, path)
2955}
2956
2957pub fn parse_program(
2959 handler: Handler,
2960 node_builder: &NodeBuilder,
2961 source: &SourceFile,
2962 modules: &[std::rc::Rc<SourceFile>],
2963 _network: NetworkName,
2964) -> Result<leo_ast::Program> {
2965 let parse = leo_parser_rowan::parse_file(&source.src);
2967 let main_context = conversion_context(
2968 &handler,
2969 node_builder,
2970 parse.lex_errors(),
2971 parse.errors(),
2972 source.absolute_start,
2973 source.src.len() as u32,
2974 );
2975 let mut program = main_context.to_main(&parse.syntax())?;
2976 let program_name = *program.program_scopes.first().unwrap().0;
2977
2978 let root_dir = match &source.name {
2980 FileName::Real(path) => path.parent().map(|p| p.to_path_buf()),
2981 _ => None,
2982 };
2983
2984 for module in modules {
2985 let module_parse = leo_parser_rowan::parse_module_entry(&module.src);
2986 let module_context = conversion_context(
2987 &handler,
2988 node_builder,
2989 module_parse.lex_errors(),
2990 module_parse.errors(),
2991 module.absolute_start,
2992 module.src.len() as u32,
2993 );
2994
2995 if let Some(key) = compute_module_key(&module.name, root_dir.as_deref()) {
2996 for segment in &key {
2997 if symbol_is_keyword(*segment) {
2998 return Err(ParserError::keyword_used_as_module_name(key.iter().format("::"), segment).into());
2999 }
3000 }
3001 let module_ast = module_context.to_module(&module_parse.syntax(), program_name, key.clone())?;
3002 program.modules.insert(key, module_ast);
3003 }
3004 }
3005
3006 Ok(program)
3007}
3008
3009pub fn parse_library(
3011 handler: Handler,
3012 node_builder: &NodeBuilder,
3013 library_name: Symbol,
3014 source: &SourceFile,
3015 modules: &[std::rc::Rc<SourceFile>],
3016 _network: NetworkName,
3017) -> Result<leo_ast::Library> {
3018 let parse = leo_parser_rowan::parse_file(&source.src);
3020 let main_context = conversion_context(
3021 &handler,
3022 node_builder,
3023 parse.lex_errors(),
3024 parse.errors(),
3025 source.absolute_start,
3026 source.src.len() as u32,
3027 );
3028
3029 let mut library = main_context.to_library(library_name, &parse.syntax())?;
3030
3031 let root_dir = match &source.name {
3033 FileName::Real(path) => path.parent().map(|p| p.to_path_buf()),
3034 _ => None,
3035 };
3036
3037 for module_sf in modules {
3039 let module_parse = leo_parser_rowan::parse_module_entry(&module_sf.src);
3040 let module_context = conversion_context(
3041 &handler,
3042 node_builder,
3043 module_parse.lex_errors(),
3044 module_parse.errors(),
3045 module_sf.absolute_start,
3046 module_sf.src.len() as u32,
3047 );
3048
3049 if let Some(key) = compute_module_key(&module_sf.name, root_dir.as_deref()) {
3050 for segment in &key {
3051 if symbol_is_keyword(*segment) {
3052 return Err(ParserError::keyword_used_as_module_name(key.iter().format("::"), segment).into());
3053 }
3054 }
3055 let module_ast = module_context.to_module(&module_parse.syntax(), library_name, key.clone())?;
3058 library.modules.insert(key, module_ast);
3059 }
3060 }
3061
3062 Ok(library)
3063}
3064
3065fn children(node: &SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ {
3071 node.children().filter(|n| !n.kind().is_trivia())
3072}
3073
3074fn tokens(node: &SyntaxNode) -> impl Iterator<Item = SyntaxToken> + '_ {
3076 node.children_with_tokens().filter_map(|elem| elem.into_token()).filter(|t| !t.kind().is_trivia())
3077}
3078
3079fn find_name_after_dot(node: &SyntaxNode) -> Option<SyntaxToken> {
3081 let dot_end = tokens(node).find(|t| t.kind() == DOT)?.text_range().end();
3082 tokens(node).filter(|t| t.text_range().start() >= dot_end).find(|t| t.kind() == IDENT || t.kind().is_keyword())
3083}
3084
3085fn first_non_trivia_token(node: &SyntaxNode) -> Option<SyntaxToken> {
3087 node.children_with_tokens().find_map(|e| e.into_token().filter(|t| !t.kind().is_trivia()))
3088}
3089
3090fn last_non_trivia_token(node: &SyntaxNode) -> Option<SyntaxToken> {
3092 node.children_with_tokens().filter_map(|e| e.into_token().filter(|t| !t.kind().is_trivia())).last()
3093}
3094
3095fn find_invalid_network(node: &SyntaxNode) -> Option<SyntaxToken> {
3097 let mut saw_dot = false;
3098 tokens(node).find(|t| {
3099 if t.kind() == DOT {
3100 saw_dot = true;
3101 return false;
3102 }
3103 saw_dot && t.kind() == IDENT
3104 })
3105}
3106
3107fn token_kind_to_mode(kind: SyntaxKind) -> Option<leo_ast::Mode> {
3109 match kind {
3110 KW_PUBLIC => Some(leo_ast::Mode::Public),
3111 KW_PRIVATE => Some(leo_ast::Mode::Private),
3112 KW_CONSTANT => Some(leo_ast::Mode::Constant),
3113 _ => None,
3114 }
3115}
3116
3117fn node_kind_to_mode(kind: SyntaxKind) -> leo_ast::Mode {
3119 match kind {
3120 PARAM_PUBLIC | STRUCT_MEMBER_PUBLIC => leo_ast::Mode::Public,
3121 PARAM_PRIVATE | STRUCT_MEMBER_PRIVATE => leo_ast::Mode::Private,
3122 PARAM_CONSTANT | STRUCT_MEMBER_CONSTANT => leo_ast::Mode::Constant,
3123 _ => leo_ast::Mode::None,
3124 }
3125}
3126
3127fn keyword_to_path_symbol(kind: SyntaxKind) -> Option<Symbol> {
3129 match kind {
3130 KW_SELF => Some(sym::SelfLower),
3131 KW_BLOCK => Some(sym::block),
3132 KW_NETWORK => Some(sym::network),
3133 KW_FINAL_UPPER => Some(sym::Final),
3134 _ => None,
3135 }
3136}
3137
3138fn is_assign_op(kind: SyntaxKind) -> bool {
3140 matches!(
3141 kind,
3142 EQ | PLUS_EQ
3143 | MINUS_EQ
3144 | STAR_EQ
3145 | SLASH_EQ
3146 | PERCENT_EQ
3147 | STAR2_EQ
3148 | AMP_EQ
3149 | PIPE_EQ
3150 | CARET_EQ
3151 | SHL_EQ
3152 | SHR_EQ
3153 | AMP2_EQ
3154 | PIPE2_EQ
3155 )
3156}
3157
3158fn keyword_to_primitive_type(kind: SyntaxKind) -> Option<leo_ast::Type> {
3160 let ty = match kind {
3161 KW_ADDRESS => leo_ast::Type::Address,
3162 KW_BOOL => leo_ast::Type::Boolean,
3163 KW_FIELD => leo_ast::Type::Field,
3164 KW_GROUP => leo_ast::Type::Group,
3165 KW_SCALAR => leo_ast::Type::Scalar,
3166 KW_SIGNATURE => leo_ast::Type::Signature,
3167 KW_STRING => leo_ast::Type::String,
3168 KW_DYN => leo_ast::Type::DynRecord,
3169 KW_IDENTIFIER => leo_ast::Type::Identifier,
3170 KW_U8 => leo_ast::Type::Integer(leo_ast::IntegerType::U8),
3171 KW_U16 => leo_ast::Type::Integer(leo_ast::IntegerType::U16),
3172 KW_U32 => leo_ast::Type::Integer(leo_ast::IntegerType::U32),
3173 KW_U64 => leo_ast::Type::Integer(leo_ast::IntegerType::U64),
3174 KW_U128 => leo_ast::Type::Integer(leo_ast::IntegerType::U128),
3175 KW_I8 => leo_ast::Type::Integer(leo_ast::IntegerType::I8),
3176 KW_I16 => leo_ast::Type::Integer(leo_ast::IntegerType::I16),
3177 KW_I32 => leo_ast::Type::Integer(leo_ast::IntegerType::I32),
3178 KW_I64 => leo_ast::Type::Integer(leo_ast::IntegerType::I64),
3179 KW_I128 => leo_ast::Type::Integer(leo_ast::IntegerType::I128),
3180 _ => return None,
3181 };
3182 Some(ty)
3183}
3184
3185fn token_to_binary_op(kind: SyntaxKind) -> leo_ast::BinaryOperation {
3187 match kind {
3188 EQ2 => leo_ast::BinaryOperation::Eq,
3189 BANG_EQ => leo_ast::BinaryOperation::Neq,
3190 LT => leo_ast::BinaryOperation::Lt,
3191 LT_EQ => leo_ast::BinaryOperation::Lte,
3192 GT => leo_ast::BinaryOperation::Gt,
3193 GT_EQ => leo_ast::BinaryOperation::Gte,
3194 PLUS => leo_ast::BinaryOperation::Add,
3195 MINUS => leo_ast::BinaryOperation::Sub,
3196 STAR => leo_ast::BinaryOperation::Mul,
3197 SLASH => leo_ast::BinaryOperation::Div,
3198 PERCENT => leo_ast::BinaryOperation::Rem,
3199 PIPE2 => leo_ast::BinaryOperation::Or,
3200 AMP2 => leo_ast::BinaryOperation::And,
3201 PIPE => leo_ast::BinaryOperation::BitwiseOr,
3202 AMP => leo_ast::BinaryOperation::BitwiseAnd,
3203 STAR2 => leo_ast::BinaryOperation::Pow,
3204 SHL => leo_ast::BinaryOperation::Shl,
3205 SHR => leo_ast::BinaryOperation::Shr,
3206 CARET => leo_ast::BinaryOperation::Xor,
3207 _ => panic!("unexpected binary operator: {:?}", kind),
3208 }
3209}
3210
3211fn symbol_is_keyword(symbol: Symbol) -> bool {
3212 matches!(
3213 symbol,
3214 sym::address
3215 | sym::aleo
3216 | sym::As
3217 | sym::assert
3218 | sym::assert_eq
3219 | sym::assert_neq
3220 | sym::block
3221 | sym::bool
3222 | sym::Const
3223 | sym::constant
3224 | sym::constructor
3225 | sym::Else
3226 | sym::False
3227 | sym::field
3228 | sym::FnUpper
3229 | sym::Fn
3230 | sym::For
3231 | sym::Final
3232 | sym::group
3233 | sym::i8
3234 | sym::i16
3235 | sym::i32
3236 | sym::i64
3237 | sym::i128
3238 | sym::If
3239 | sym::import
3240 | sym::In
3241 | sym::inline
3242 | sym::Let
3243 | sym::leo
3244 | sym::mapping
3245 | sym::storage
3246 | sym::network
3247 | sym::private
3248 | sym::program
3249 | sym::public
3250 | sym::record
3251 | sym::Return
3252 | sym::scalar
3253 | sym::script
3254 | sym::SelfLower
3255 | sym::signature
3256 | sym::string
3257 | sym::Struct
3258 | sym::True
3259 | sym::u8
3260 | sym::u16
3261 | sym::u32
3262 | sym::u64
3263 | sym::u128
3264 )
3265}
3266
3267fn compute_module_key(name: &FileName, root_dir: Option<&std::path::Path>) -> Option<Vec<Symbol>> {
3269 let path = match name {
3270 FileName::Custom(name) => std::path::Path::new(name).to_path_buf(),
3271 FileName::Real(path) => {
3272 let root = root_dir?;
3273 path.strip_prefix(root).ok()?.to_path_buf()
3274 }
3275 };
3276
3277 let mut key: Vec<Symbol> =
3278 path.components().map(|comp| Symbol::intern(&comp.as_os_str().to_string_lossy())).collect();
3279
3280 if let Some(last) = path.file_name()
3281 && let Some(stem) = std::path::Path::new(last).file_stem()
3282 {
3283 key.pop();
3284 key.push(Symbol::intern(&stem.to_string_lossy()));
3285 }
3286
3287 Some(key)
3288}
3289
3290fn is_library_item(kind: SyntaxKind) -> bool {
3292 matches!(kind, GLOBAL_CONST | STRUCT_DEF | FUNCTION_DEF | INTERFACE_DEF)
3293}
3294
3295fn is_program_item(kind: SyntaxKind) -> bool {
3297 matches!(
3298 kind,
3299 GLOBAL_CONST
3300 | FUNCTION_DEF
3301 | FINAL_FN_DEF
3302 | STRUCT_DEF
3303 | RECORD_DEF
3304 | INTERFACE_DEF
3305 | MAPPING_DEF
3306 | STORAGE_DEF
3307 | CONSTRUCTOR_DEF
3308 | PROGRAM_DECL
3309 | IMPORT
3310 )
3311}