1use itertools::Itertools as _;
31use snarkvm::prelude::{Address, Signature, TestnetV0};
32
33use leo_ast::{NetworkName, NodeBuilder};
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 mut idents = tokens(node).filter(|t| t.kind() == IDENT);
306 let program_token = idents.next();
307 let name_token = idents.next();
308
309 let kw_aleo_token =
311 tokens(node).find(|t| t.kind() == KW_ALEO).expect("TYPE_LOCATOR should contain `aleo` keyword");
312
313 let network_ident = leo_ast::Identifier {
314 name: Symbol::intern("aleo"),
315 span: self.token_span(&kw_aleo_token),
316 id: self.builder.next_id(),
317 };
318
319 match (program_token, name_token) {
320 (Some(program_token), Some(name_token)) => {
321 let program_ident = self.to_identifier(&program_token);
323 let type_ident = self.to_identifier(&name_token);
324 let program_id = leo_ast::ProgramId { name: program_ident, network: network_ident };
325 let path_span = Span::new(program_id.name.span.lo, type_ident.span.hi);
326 let path =
327 leo_ast::Path::new(Some(program_id), Vec::new(), type_ident, path_span, self.builder.next_id());
328 let (_type_parameters, const_arguments) = self.extract_const_arg_list(node)?;
329 Ok(leo_ast::CompositeType { path, const_arguments }.into())
330 }
331 (Some(program_token), None) => {
332 let program_ident = self.to_identifier(&program_token);
334 let program_id = leo_ast::ProgramId { name: program_ident, network: network_ident };
335 let span = self.content_span(node);
336 let path =
337 leo_ast::Path::new(Some(program_id), Vec::new(), program_ident, span, self.builder.next_id());
338 Ok(leo_ast::CompositeType { path, const_arguments: Vec::new() }.into())
339 }
340 _ => {
341 panic!("TYPE_LOCATOR should contain at least a program IDENT: {:?}", node.text())
342 }
343 }
344 }
345
346 fn type_path_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
350 debug_assert_eq!(node.kind(), TYPE_PATH);
351
352 let mut path_components = Vec::new();
354
355 for token in tokens(node) {
357 match token.kind() {
358 IDENT => {
359 path_components.push(self.to_identifier(&token));
360 }
361 COLON_COLON | L_BRACKET | R_BRACKET | LT | GT | COMMA | INTEGER => {}
363 kind if kind.is_trivia() => {}
364 kind => panic!("unexpected token in TYPE_PATH: {:?}", kind),
365 }
366 }
367
368 let (_type_parameters, const_arguments) = self.extract_const_arg_list(node)?;
370
371 let name = path_components.pop().expect("TYPE_PATH should have at least one identifier");
374 let path_span =
375 if let Some(first) = path_components.first() { Span::new(first.span.lo, name.span.hi) } else { name.span };
376 let path = leo_ast::Path::new(None, path_components, name, path_span, self.builder.next_id());
377 Ok(leo_ast::CompositeType { path, const_arguments }.into())
378 }
379
380 fn type_array_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
382 debug_assert_eq!(node.kind(), TYPE_ARRAY);
383
384 let element_node = children(node).find(|n| n.kind().is_type()).expect("array type should have element type");
385 let element_type = self.to_type(&element_node)?;
386 let length_expr = self.array_length_to_expression(node)?;
387 Ok(leo_ast::ArrayType { element_type: Box::new(element_type), length: Box::new(length_expr) }.into())
388 }
389
390 fn type_vector_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
392 debug_assert_eq!(node.kind(), TYPE_VECTOR);
393
394 let element_node = children(node).find(|n| n.kind().is_type()).expect("vector type should have element type");
395 let element_type = self.to_type(&element_node)?;
396 Ok(leo_ast::VectorType { element_type: Box::new(element_type) }.into())
397 }
398
399 fn array_length_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
401 match children(node).find(|n| n.kind() == ARRAY_LENGTH) {
402 Some(length_node) => self.require_expression(&length_node, "array length"),
403 None => {
404 let span = self.to_span(node);
406 self.emit_unexpected_str("array length", node.text(), span);
407 Ok(self.error_expression(span))
408 }
409 }
410 }
411
412 fn integer_token_to_expression(&self, token: &SyntaxToken) -> Result<leo_ast::Expression> {
414 debug_assert_eq!(token.kind(), INTEGER);
415 let text = token.text();
416 let span = self.token_span(token);
417 let id = self.builder.next_id();
418
419 let suffixes = [
421 ("u128", leo_ast::IntegerType::U128),
422 ("u64", leo_ast::IntegerType::U64),
423 ("u32", leo_ast::IntegerType::U32),
424 ("u16", leo_ast::IntegerType::U16),
425 ("u8", leo_ast::IntegerType::U8),
426 ("i128", leo_ast::IntegerType::I128),
427 ("i64", leo_ast::IntegerType::I64),
428 ("i32", leo_ast::IntegerType::I32),
429 ("i16", leo_ast::IntegerType::I16),
430 ("i8", leo_ast::IntegerType::I8),
431 ];
432
433 for (suffix, int_type) in suffixes {
434 if text.ends_with(suffix) {
435 let value = text.strip_suffix(suffix).unwrap().to_string();
437 return Ok(leo_ast::Literal::integer(int_type, value, span, id).into());
438 }
439 }
440
441 Ok(leo_ast::Literal::unsuffixed(text.to_string(), span, id).into())
443 }
444
445 fn type_tuple_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
447 debug_assert_eq!(node.kind(), TYPE_TUPLE);
448 let span = self.to_span(node);
449
450 let type_nodes: Vec<_> = children(node).filter(|n| n.kind().is_type()).collect();
451
452 if type_nodes.is_empty() {
453 return Ok(leo_ast::Type::Unit);
455 }
456
457 let elements = type_nodes.iter().map(|n| self.to_type(n)).collect::<Result<Vec<_>>>()?;
458
459 if elements.len() == 1 {
460 self.handler.emit_err(ParserError::tuple_must_have_at_least_two_elements("type", span));
462 return Ok(elements.into_iter().next().unwrap());
464 }
465
466 Ok(leo_ast::TupleType::new(elements).into())
467 }
468
469 fn type_optional_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
471 debug_assert_eq!(node.kind(), TYPE_OPTIONAL);
472
473 let inner_node = children(node).find(|n| n.kind().is_type()).expect("optional type should have inner type");
474
475 let inner = self.to_type(&inner_node)?;
476 Ok(leo_ast::Type::Optional(leo_ast::OptionalType { inner: Box::new(inner) }))
477 }
478
479 fn type_final_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
481 debug_assert_eq!(node.kind(), TYPE_FINAL);
482
483 let type_nodes: Vec<_> = children(node).filter(|n| n.kind().is_type()).collect();
485
486 if type_nodes.is_empty() {
487 return Ok(leo_ast::FutureType::default().into());
489 }
490
491 let types = type_nodes.iter().map(|n| self.to_type(n)).collect::<Result<Vec<_>>>()?;
493
494 Ok(leo_ast::FutureType::new(types, None, true).into())
495 }
496
497 fn type_mapping_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
498 debug_assert_eq!(node.kind(), TYPE_MAPPING);
499 let mut type_nodes = children(node).filter(|n| n.kind().is_type());
500 let key = type_nodes.next().map(|n| self.to_type(&n)).transpose()?.unwrap_or(leo_ast::Type::Err);
501 let value = type_nodes.next().map(|n| self.to_type(&n)).transpose()?.unwrap_or(leo_ast::Type::Err);
502 Ok(leo_ast::Type::Mapping(leo_ast::MappingType { key: Box::new(key), value: Box::new(value) }))
503 }
504
505 fn to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
511 let span = self.content_span(node);
512
513 let expr = match node.kind() {
514 LITERAL_FIELD => self.suffixed_literal_to_expression(node, "field", leo_ast::Literal::field)?,
515 LITERAL_GROUP => self.suffixed_literal_to_expression(node, "group", leo_ast::Literal::group)?,
516 LITERAL_SCALAR => self.suffixed_literal_to_expression(node, "scalar", leo_ast::Literal::scalar)?,
517 LITERAL_INT => self.int_literal_to_expression(node)?,
518 LITERAL_STRING => self.string_literal_to_expression(node)?,
519 LITERAL_ADDRESS => self.address_literal_to_expression(node)?,
520 LITERAL_BOOL => self.bool_literal_to_expression(node)?,
521 LITERAL_NONE => leo_ast::Literal::none(span, self.builder.next_id()).into(),
522 LITERAL_IDENT => self.identifier_literal_to_expression(node)?,
523 BINARY_EXPR => self.binary_expr_to_expression(node)?,
524 UNARY_EXPR => self.unary_expr_to_expression(node)?,
525 CALL_EXPR => self.call_expr_to_expression(node)?,
526 DYNAMIC_CALL_EXPR => self.dynamic_call_expr_to_expression(node)?,
527 METHOD_CALL_EXPR => self.method_call_expr_to_expression(node)?,
528 FIELD_EXPR => self.field_expr_to_expression(node)?,
529 TUPLE_ACCESS_EXPR => self.tuple_access_expr_to_expression(node)?,
530 INDEX_EXPR => self.index_expr_to_expression(node)?,
531 CAST_EXPR => self.cast_expr_to_expression(node)?,
532 TERNARY_EXPR => self.ternary_expr_to_expression(node)?,
533 ARRAY_EXPR => self.array_expr_to_expression(node)?,
534 REPEAT_EXPR => self.repeat_expr_to_expression(node)?,
535 TUPLE_EXPR => self.tuple_expr_to_expression(node)?,
536 STRUCT_EXPR => self.struct_expr_to_expression(node)?,
537 STRUCT_LOCATOR_EXPR => self.struct_locator_expr_to_expression(node)?,
538 PATH_EXPR => self.path_expr_to_expression(node)?,
539 PATH_LOCATOR_EXPR => self.path_locator_expr_to_expression(node)?,
540 PROGRAM_REF_EXPR => self.program_ref_expr_to_expression(node)?,
541 SELF_EXPR => self.keyword_expr_to_path(node, sym::SelfLower)?,
542 BLOCK_KW_EXPR => self.keyword_expr_to_path(node, sym::block)?,
543 NETWORK_KW_EXPR => self.keyword_expr_to_path(node, sym::network)?,
544 PAREN_EXPR => {
545 if let Some(inner) = children(node).find(|n| n.kind().is_expression()) {
547 self.to_expression(&inner)?
548 } else {
549 self.emit_unexpected_str("expression in parentheses", node.text(), span);
551 self.error_expression(span)
552 }
553 }
554 FINAL_EXPR => self.final_expr_to_expression(node)?,
556 ROOT => {
558 if let Some(inner) = children(node).find(|n| n.kind().is_expression()) {
559 self.to_expression(&inner)?
560 } else {
561 self.error_expression(span)
563 }
564 }
565 ERROR => self.error_expression(span),
568 kind => panic!("unexpected expression kind: {:?}", kind),
569 };
570
571 Ok(expr)
572 }
573
574 fn suffixed_literal_to_expression(
576 &self,
577 node: &SyntaxNode,
578 suffix: &str,
579 ctor: fn(String, Span, leo_ast::NodeID) -> leo_ast::Literal,
580 ) -> Result<leo_ast::Expression> {
581 let span = self.content_span(node);
582 let id = self.builder.next_id();
583 let token = tokens(node).next().expect("literal node should have a token");
584 let text = token.text();
585 self.validate_hexbin_literal(text, suffix.len() as u32, span);
586 let value = text.strip_suffix(suffix).unwrap();
587 Ok(ctor(value.to_string(), span, id).into())
588 }
589
590 fn int_literal_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
592 let token = tokens(node).next().expect("LITERAL_INT should have a token");
593 self.integer_token_to_expression(&token)
594 }
595
596 fn string_literal_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
598 let span = self.content_span(node);
599 let id = self.builder.next_id();
600 let token = tokens(node).next().expect("LITERAL_STRING should have a token");
601 Ok(leo_ast::Literal::string(token.text().to_string(), span, id).into())
602 }
603
604 fn identifier_literal_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
606 let span = self.content_span(node);
607 let id = self.builder.next_id();
608 let token = tokens(node).next().expect("LITERAL_IDENT should have a token");
609 let text = token.text();
611 let content = &text[1..text.len() - 1];
612 Ok(leo_ast::Literal::identifier(content.to_string(), span, id).into())
613 }
614
615 fn address_literal_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
617 let span = self.content_span(node);
618 let id = self.builder.next_id();
619 let token = tokens(node).next().expect("LITERAL_ADDRESS should have a token");
620 let text = token.text();
621 if !text.contains(".aleo") && text.parse::<Address<TestnetV0>>().is_err() {
623 self.handler.emit_err(ParserError::invalid_address_lit(text, span));
624 }
625 Ok(leo_ast::Literal::address(text.to_string(), span, id).into())
626 }
627
628 fn bool_literal_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
630 let span = self.content_span(node);
631 let id = self.builder.next_id();
632 let token = tokens(node).next().expect("LITERAL_BOOL should have a token");
633 let value = token.kind() == KW_TRUE;
634 Ok(leo_ast::Literal::boolean(value, span, id).into())
635 }
636
637 fn binary_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
639 debug_assert_eq!(node.kind(), BINARY_EXPR);
640 let span = self.content_span(node);
641 let id = self.builder.next_id();
642
643 let mut operands = children(node).filter(|n| n.kind().is_expression() || n.kind().is_type());
644
645 let op_token = match tokens(node).find(|t| t.kind().is_operator() || t.kind() == KW_AS) {
647 Some(token) => token,
648 None => {
649 self.emit_unexpected_str("operator in binary expression", node.text(), span);
650 return Ok(self.error_expression(span));
651 }
652 };
653
654 let op = token_to_binary_op(op_token.kind());
655
656 let left = match operands.next() {
658 Some(left_node) => self.to_expression(&left_node)?,
659 None => {
660 self.emit_unexpected_str("left operand in binary expression", node.text(), span);
661 return Ok(self.error_expression(span));
662 }
663 };
664
665 if op_token.kind() == KW_AS {
667 self.emit_unexpected_str("cast expression", "binary AS expression", span);
668 return Ok(self.error_expression(span));
669 }
670
671 let right = match operands.next() {
673 Some(right_node) => self.to_expression(&right_node)?,
674 None => {
675 self.emit_unexpected_str("right operand in binary expression", node.text(), span);
676 return Ok(self.error_expression(span));
677 }
678 };
679
680 Ok(leo_ast::BinaryExpression { left, right, op, span, id }.into())
681 }
682
683 fn unary_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
685 debug_assert_eq!(node.kind(), UNARY_EXPR);
686 let span = self.content_span(node);
687 let id = self.builder.next_id();
688
689 let Some(op_token) = tokens(node).find(|t| matches!(t.kind(), BANG | MINUS)) else {
691 self.emit_unexpected_str("operator in unary expression", node.text(), span);
692 return Ok(self.error_expression(span));
693 };
694
695 let op = if op_token.kind() == BANG { leo_ast::UnaryOperation::Not } else { leo_ast::UnaryOperation::Negate };
696
697 let Some(operand) = children(node).find(|n| n.kind().is_expression()) else {
699 self.emit_unexpected_str("operand in unary expression", node.text(), span);
700 return Ok(self.error_expression(span));
701 };
702
703 let mut receiver = self.to_expression(&operand)?;
704
705 if op == leo_ast::UnaryOperation::Negate
707 && let leo_ast::Expression::Literal(leo_ast::Literal {
708 variant:
709 leo_ast::LiteralVariant::Integer(_, ref mut string)
710 | leo_ast::LiteralVariant::Field(ref mut string)
711 | leo_ast::LiteralVariant::Group(ref mut string)
712 | leo_ast::LiteralVariant::Scalar(ref mut string),
713 span: ref mut lit_span,
714 ..
715 }) = receiver
716 && !string.starts_with('-')
717 {
718 string.insert(0, '-');
719 *lit_span = span;
720 return Ok(receiver);
721 }
722
723 Ok(leo_ast::UnaryExpression { receiver, op, span, id }.into())
724 }
725
726 fn extract_const_arg_list(&self, node: &SyntaxNode) -> Result<ConstArgList> {
733 let mut type_parameters = Vec::new();
734 let mut const_arguments = Vec::new();
735 if let Some(arg_list) = children(node).find(|n| n.kind() == CONST_ARG_LIST) {
736 for child in children(&arg_list) {
737 if child.kind() == DYNAMIC_CALL_RETURN_TYPE {
738 if let Some(type_node) = children(&child).find(|n| n.kind().is_type()) {
741 let span = self.content_span(&child);
742 let ty = self.to_type(&type_node)?;
743 type_parameters.push((ty, span));
744 }
745 } else if child.kind().is_type() {
746 let span = self.content_span(&child);
747 let ty = self.to_type(&child)?;
748 type_parameters.push((ty, span));
749 } else if child.kind().is_expression() {
750 let expr = self.to_expression(&child)?;
751 const_arguments.push(expr);
752 }
753 }
754 }
755 Ok((type_parameters, const_arguments))
756 }
757
758 fn extract_dynamic_call_types(
768 &self,
769 callee_node: &SyntaxNode,
770 type_parameters: &[(leo_ast::Type, Span)],
771 ) -> Result<(AnnotatedTypes, AnnotatedTypes)> {
772 let Some(arg_list) = children(callee_node).find(|n| n.kind() == CONST_ARG_LIST) else {
773 return Ok((Vec::new(), Vec::new()));
774 };
775
776 let mut all_entries = Vec::new();
778
779 for child in children(&arg_list) {
780 if child.kind() == DYNAMIC_CALL_RETURN_TYPE {
781 let mode = tokens(&child).find_map(|tok| token_kind_to_mode(tok.kind())).unwrap_or(leo_ast::Mode::None);
782 all_entries.push(mode);
783 } else if child.kind().is_type() {
784 all_entries.push(leo_ast::Mode::None);
785 }
786 }
787
788 if type_parameters.is_empty() {
790 return Ok((Vec::new(), Vec::new()));
791 }
792
793 let mut input_types = Vec::new();
794 let mut return_types = Vec::new();
795
796 let last_idx = type_parameters.len() - 1;
797 for (i, ((ty, sp), mode)) in type_parameters.iter().zip(all_entries.iter()).enumerate() {
798 if i < last_idx {
799 input_types.push((*mode, ty.clone(), *sp));
801 } else {
802 match ty {
807 leo_ast::Type::Unit => {}
808 leo_ast::Type::Tuple(tuple) => {
809 for elem in tuple.elements() {
810 return_types.push((*mode, elem.clone(), *sp));
811 }
812 }
813 _ => {
814 return_types.push((*mode, ty.clone(), *sp));
815 }
816 }
817 }
818 }
819
820 Ok((input_types, return_types))
821 }
822
823 fn call_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
825 debug_assert_eq!(node.kind(), CALL_EXPR);
826 let span = self.content_span(node);
827 let id = self.builder.next_id();
828
829 let mut child_iter = children(node);
831 let callee_node = child_iter.next().expect("call expr should have callee");
832
833 let function = match callee_node.kind() {
834 PATH_LOCATOR_EXPR => self.locator_tokens_to_path(&callee_node)?,
835 _ => self.path_expr_to_path(&callee_node)?,
836 };
837
838 let arguments = children(node)
840 .skip(1) .filter(|n| n.kind().is_expression())
842 .map(|n| self.to_expression(&n))
843 .collect::<Result<Vec<_>>>()?;
844
845 let (type_parameters, const_arguments) = self.extract_const_arg_list(&callee_node)?;
848
849 if function.user_program().is_none() && function.qualifier().len() == 1 {
853 let module = function.qualifier()[0].name;
854 let name = function.identifier().name;
855 if let Some(intrinsic_name) = leo_ast::Intrinsic::convert_path_symbols(module, name) {
856 return Ok(leo_ast::IntrinsicExpression {
857 name: intrinsic_name,
858 type_parameters,
859 input_types: Vec::new(),
860 return_types: Vec::new(),
861 arguments,
862 span,
863 id,
864 }
865 .into());
866 }
867 }
868
869 if function.user_program().is_none() && function.qualifier().is_empty() {
872 let name = function.identifier().name;
873 if leo_ast::Intrinsic::from_symbol(name, &type_parameters).is_some() {
874 let (input_types, return_types) = if name == leo_span::sym::_dynamic_call {
877 self.extract_dynamic_call_types(&callee_node, &type_parameters)?
878 } else {
879 (Vec::new(), Vec::new())
880 };
881 return Ok(leo_ast::IntrinsicExpression {
882 name,
883 type_parameters,
884 input_types,
885 return_types,
886 arguments,
887 span,
888 id,
889 }
890 .into());
891 }
892 }
893
894 Ok(leo_ast::CallExpression { function, const_arguments, arguments, span, id }.into())
895 }
896
897 fn dynamic_call_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
899 debug_assert_eq!(node.kind(), DYNAMIC_CALL_EXPR);
900 let span = self.content_span(node);
901 let id = self.builder.next_id();
902
903 let interface = children(node)
904 .filter(|n| n.kind().is_type())
905 .map(|n| self.to_type(&n))
906 .next()
907 .expect("Parser guarantees a type")?;
908
909 let function = if let Some(token) = tokens(node).find(|t| t.kind() == IDENT) {
910 self.to_identifier(&token)
911 } else {
912 self.error_identifier(span)
913 };
914
915 let separator_offset = tokens(node).filter(|t| t.kind() == COLON_COLON).last().map(|t| t.text_range().start());
921
922 let expr_children: Vec<_> = children(node).filter(|n| n.kind().is_expression()).collect();
923
924 let mut pre_sep = Vec::new();
925 let mut post_sep = Vec::new();
926 for child in &expr_children {
927 if let Some(sep_off) = separator_offset {
928 if child.text_range().start() < sep_off {
929 pre_sep.push(child);
930 } else {
931 post_sep.push(child);
932 }
933 } else {
934 pre_sep.push(child);
936 }
937 }
938
939 let target = if let Some(target_node) = pre_sep.first() {
940 self.to_expression(target_node)?
941 } else {
942 self.error_expression(span)
943 };
944
945 let network =
946 if let Some(network_node) = pre_sep.get(1) { Some(self.to_expression(network_node)?) } else { None };
947
948 let arguments = post_sep.iter().map(|n| self.to_expression(n)).collect::<Result<Vec<_>>>()?;
949
950 Ok(leo_ast::DynamicCallExpression { interface, target_program: target, network, function, arguments, span, id }
951 .into())
952 }
953
954 fn method_call_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
958 debug_assert_eq!(node.kind(), METHOD_CALL_EXPR);
959 let span = self.content_span(node);
960 let id = self.builder.next_id();
961
962 let mut expr_children = children(node).filter(|n| n.kind().is_expression());
964 let receiver = match expr_children.next() {
965 Some(receiver_node) => self.to_expression(&receiver_node)?,
966 None => {
967 self.emit_unexpected_str("receiver in method call", node.text(), span);
968 return Ok(self.error_expression(span));
969 }
970 };
971
972 let method_name = match find_name_after_dot(node) {
974 Some(method_token) => self.to_identifier(&method_token),
975 None => {
976 self.emit_unexpected_str("method name in method call", node.text(), span);
977 return Ok(self.error_expression(span));
978 }
979 };
980
981 let mut args: Vec<_> = expr_children.map(|n| self.to_expression(&n)).collect::<Result<Vec<_>>>()?;
983
984 if args.is_empty() {
986 if let Some(op) = leo_ast::UnaryOperation::from_symbol(method_name.name) {
987 return Ok(leo_ast::UnaryExpression { span, op, receiver, id }.into());
988 }
989 } else if args.len() == 1
990 && let Some(op) = leo_ast::BinaryOperation::from_symbol(method_name.name)
991 {
992 return Ok(leo_ast::BinaryExpression { span, op, left: receiver, right: args.pop().unwrap(), id }.into());
993 }
994
995 let method = method_name.name;
1001 let all_args = || std::iter::once(receiver.clone()).chain(args.clone()).collect::<Vec<_>>();
1002
1003 let intrinsic_name = match args.len() {
1005 2 => leo_ast::Intrinsic::convert_path_symbols(sym::signature, method),
1006 0 => leo_ast::Intrinsic::convert_path_symbols(sym::Final, method)
1007 .or_else(|| leo_ast::Intrinsic::convert_path_symbols(sym::Optional, method)),
1008 1 => leo_ast::Intrinsic::convert_path_symbols(sym::Optional, method),
1009 _ => None,
1010 };
1011 if let Some(intrinsic_name) = intrinsic_name {
1012 return Ok(self.intrinsic_expression(intrinsic_name, all_args(), span));
1013 }
1014
1015 if method == sym::get && args.len() == 1 {
1018 return Ok(self.intrinsic_expression(Symbol::intern("__unresolved_get"), all_args(), span));
1019 }
1020 if method == sym::set && args.len() == 2 {
1021 return Ok(self.intrinsic_expression(Symbol::intern("__unresolved_set"), all_args(), span));
1022 }
1023
1024 for module in [sym::Vector, sym::Mapping] {
1026 if let Some(intrinsic_name) = leo_ast::Intrinsic::convert_path_symbols(module, method) {
1027 return Ok(self.intrinsic_expression(intrinsic_name, all_args(), span));
1028 }
1029 }
1030
1031 self.handler.emit_err(ParserError::invalid_method_call(receiver, method_name, args.len(), span));
1033 Ok(self.error_expression(span))
1034 }
1035
1036 fn tuple_access_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1038 debug_assert_eq!(node.kind(), TUPLE_ACCESS_EXPR);
1039 let span = self.content_span(node);
1040 let id = self.builder.next_id();
1041
1042 let inner = if let Some(inner_node) = children(node).find(|n| n.kind().is_expression()) {
1043 self.to_expression(&inner_node)?
1044 } else {
1045 self.emit_unexpected_str("expression in tuple access", node.text(), span);
1046 return Ok(self.error_expression(span));
1047 };
1048
1049 let index_token = match tokens(node).find(|t| t.kind() == INTEGER) {
1050 Some(token) => token,
1051 None => {
1052 self.emit_unexpected_str("tuple index", node.text(), span);
1053 return Ok(self.error_expression(span));
1054 }
1055 };
1056
1057 let index_text = index_token.text().replace('_', "");
1058 let index: usize = match index_text.parse() {
1059 Ok(idx) => idx,
1060 Err(_) => {
1061 self.emit_unexpected_str("valid tuple index", index_text, span);
1062 return Ok(self.error_expression(span));
1063 }
1064 };
1065 Ok(leo_ast::TupleAccess { tuple: inner, index: index.into(), span, id }.into())
1066 }
1067
1068 fn field_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1070 debug_assert_eq!(node.kind(), FIELD_EXPR);
1071 let span = self.content_span(node);
1072 let id = self.builder.next_id();
1073
1074 let (inner, first_child_kind) = match children(node).find(|n| n.kind().is_expression()) {
1076 Some(n) => {
1077 let kind = n.kind();
1078 (self.to_expression(&n)?, kind)
1079 }
1080 None => {
1081 self.emit_unexpected_str("expression in field access", node.text(), span);
1082 return Ok(self.error_expression(span));
1083 }
1084 };
1085
1086 let field_token = match find_name_after_dot(node) {
1089 Some(token) => token,
1090 None => {
1091 self.emit_unexpected_str("field name in field access", node.text(), span);
1092 return Ok(self.error_expression(span));
1093 }
1094 };
1095
1096 if field_token.kind() == KW_ALEO
1100 && let leo_ast::Expression::Path(ref path) = inner
1101 && path.user_program().is_none()
1102 && path.qualifier().is_empty()
1103 {
1104 let full_name = format!("{}.aleo", path.identifier().name);
1105 return Ok(leo_ast::Literal::address(full_name, span, id).into());
1106 }
1107
1108 let field_name = Symbol::intern(field_token.text());
1110
1111 let special = match (first_child_kind, field_name) {
1112 (SELF_EXPR, sym::address) => Some(sym::_self_address),
1113 (SELF_EXPR, sym::caller) => Some(sym::_self_caller),
1114 (SELF_EXPR, sym::checksum) => Some(sym::_self_checksum),
1115 (SELF_EXPR, sym::edition) => Some(sym::_self_edition),
1116 (SELF_EXPR, sym::id) => Some(sym::_self_id),
1117 (SELF_EXPR, sym::program_owner) => Some(sym::_self_program_owner),
1118 (SELF_EXPR, sym::signer) => Some(sym::_self_signer),
1119 (BLOCK_KW_EXPR, sym::height) => Some(sym::_block_height),
1120 (BLOCK_KW_EXPR, sym::timestamp) => Some(sym::_block_timestamp),
1121 (NETWORK_KW_EXPR, sym::id) => Some(sym::_network_id),
1122 (SELF_EXPR | BLOCK_KW_EXPR | NETWORK_KW_EXPR, _) => {
1123 self.handler.emit_err(ParserError::custom("Unsupported special access", span));
1124 return Ok(self.error_expression(span));
1125 }
1126 _ => None,
1127 };
1128
1129 if let Some(intrinsic_name) = special {
1130 return Ok(self.intrinsic_expression(intrinsic_name, Vec::new(), span));
1131 }
1132
1133 let name = leo_ast::Identifier {
1135 name: Symbol::intern(field_token.text()),
1136 span: self.token_span(&field_token),
1137 id: self.builder.next_id(),
1138 };
1139 Ok(leo_ast::MemberAccess { inner, name, span, id }.into())
1140 }
1141
1142 fn index_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1144 debug_assert_eq!(node.kind(), INDEX_EXPR);
1145 let span = self.content_span(node);
1146 let id = self.builder.next_id();
1147
1148 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1149
1150 let array = match exprs.next() {
1151 Some(n) => self.to_expression(&n)?,
1152 None => {
1153 self.emit_unexpected_str("array in index expression", node.text(), span);
1154 return Ok(self.error_expression(span));
1155 }
1156 };
1157
1158 let index = match exprs.next() {
1159 Some(n) => self.to_expression(&n)?,
1160 None => {
1161 self.emit_unexpected_str("index in index expression", node.text(), span);
1162 return Ok(self.error_expression(span));
1163 }
1164 };
1165
1166 Ok(leo_ast::ArrayAccess { array, index, span, id }.into())
1167 }
1168
1169 fn cast_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1171 debug_assert_eq!(node.kind(), CAST_EXPR);
1172 let span = self.content_span(node);
1173 let id = self.builder.next_id();
1174
1175 let Some(expr_node) = children(node).find(|n| n.kind().is_expression()) else {
1177 self.emit_unexpected_str("expression in cast", node.text(), span);
1178 return Ok(self.error_expression(span));
1179 };
1180 let expression = self.to_expression(&expr_node)?;
1181
1182 let Some(type_node) = children(node).find(|n| n.kind().is_type()) else {
1184 self.emit_unexpected_str("type in cast expression", node.text(), span);
1185 return Ok(self.error_expression(span));
1186 };
1187 let type_ = self.to_type(&type_node)?;
1188
1189 Ok(leo_ast::CastExpression { expression, type_, span, id }.into())
1190 }
1191
1192 fn ternary_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1194 debug_assert_eq!(node.kind(), TERNARY_EXPR);
1195 let span = self.content_span(node);
1196 let id = self.builder.next_id();
1197
1198 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1199
1200 let condition = match exprs.next() {
1201 Some(n) => self.to_expression(&n)?,
1202 None => {
1203 self.emit_unexpected_str("condition in ternary expression", node.text(), span);
1204 return Ok(self.error_expression(span));
1205 }
1206 };
1207
1208 let if_true = match exprs.next() {
1209 Some(n) => self.to_expression(&n)?,
1210 None => {
1211 self.emit_unexpected_str("true branch in ternary expression", node.text(), span);
1212 return Ok(self.error_expression(span));
1213 }
1214 };
1215
1216 let if_false = match exprs.next() {
1217 Some(n) => self.to_expression(&n)?,
1218 None => {
1219 self.emit_unexpected_str("false branch in ternary expression", node.text(), span);
1220 return Ok(self.error_expression(span));
1221 }
1222 };
1223
1224 Ok(leo_ast::TernaryExpression { condition, if_true, if_false, span, id }.into())
1225 }
1226
1227 fn array_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1229 debug_assert_eq!(node.kind(), ARRAY_EXPR);
1230 let span = self.content_span(node);
1231 let id = self.builder.next_id();
1232
1233 let elements = children(node)
1234 .filter(|n| n.kind().is_expression())
1235 .map(|n| self.to_expression(&n))
1236 .collect::<Result<Vec<_>>>()?;
1237
1238 Ok(leo_ast::ArrayExpression { elements, span, id }.into())
1239 }
1240
1241 fn repeat_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1243 debug_assert_eq!(node.kind(), REPEAT_EXPR);
1244 let span = self.content_span(node);
1245 let id = self.builder.next_id();
1246
1247 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1248 let expr = match exprs.next() {
1249 Some(n) => self.to_expression(&n)?,
1250 None => {
1251 self.emit_unexpected_str("expression in repeat", node.text(), span);
1252 return Ok(self.error_expression(span));
1253 }
1254 };
1255 let count = match exprs.next() {
1256 Some(n) => self.to_expression(&n)?,
1257 None => {
1258 self.emit_unexpected_str("repeat count", node.text(), span);
1259 return Ok(self.error_expression(span));
1260 }
1261 };
1262
1263 Ok(leo_ast::RepeatExpression { expr, count, span, id }.into())
1264 }
1265
1266 fn tuple_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1268 debug_assert_eq!(node.kind(), TUPLE_EXPR);
1269 let span = self.content_span(node);
1270 let id = self.builder.next_id();
1271
1272 let elements: Vec<_> = children(node)
1273 .filter(|n| n.kind().is_expression())
1274 .map(|n| self.to_expression(&n))
1275 .collect::<Result<Vec<_>>>()?;
1276
1277 match elements.len() {
1278 0 => {
1279 self.handler.emit_err(ParserError::tuple_must_have_at_least_two_elements("expression", span));
1281 Ok(leo_ast::UnitExpression { span, id }.into())
1283 }
1284 1 => {
1285 self.handler.emit_err(ParserError::tuple_must_have_at_least_two_elements("expression", span));
1287 Ok(elements.into_iter().next().unwrap())
1289 }
1290 _ => Ok(leo_ast::TupleExpression { elements, span, id }.into()),
1291 }
1292 }
1293
1294 fn composite_expression_from_path(
1297 &self,
1298 node: &SyntaxNode,
1299 path: leo_ast::Path,
1300 span: Span,
1301 id: leo_ast::NodeID,
1302 ) -> Result<leo_ast::Expression> {
1303 let members = children(node)
1304 .filter(|n| matches!(n.kind(), STRUCT_FIELD_INIT | STRUCT_FIELD_SHORTHAND))
1305 .map(|n| self.struct_field_init_to_member(&n))
1306 .collect::<Result<Vec<_>>>()?;
1307 let (_type_parameters, const_arguments) = self.extract_const_arg_list(node)?;
1308 Ok(leo_ast::CompositeExpression { path, const_arguments, members, span, id }.into())
1309 }
1310
1311 fn struct_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1313 debug_assert_eq!(node.kind(), STRUCT_EXPR);
1314 let span = self.content_span(node);
1315 let id = self.builder.next_id();
1316 let path = self.struct_expr_to_path(node)?;
1317 self.composite_expression_from_path(node, path, span, id)
1318 }
1319
1320 fn struct_expr_to_path(&self, node: &SyntaxNode) -> Result<leo_ast::Path> {
1322 let fallback_span = self.content_span(node);
1323
1324 let mut path_components = Vec::new();
1326 for token in tokens(node) {
1327 if token.kind() == L_BRACE {
1328 break;
1329 }
1330 if token.kind() == IDENT {
1331 path_components.push(self.to_identifier(&token));
1332 }
1333 }
1334
1335 let path_span = match (path_components.first(), path_components.last()) {
1336 (Some(first), Some(last)) => Span::new(first.span.lo, last.span.hi),
1337 _ => fallback_span,
1338 };
1339
1340 let name = match path_components.pop() {
1341 Some(name) => name,
1342 None => {
1343 self.emit_unexpected_str("type name in struct expression", node.text(), fallback_span);
1344 self.error_identifier(fallback_span)
1345 }
1346 };
1347 Ok(leo_ast::Path::new(None, path_components, name, path_span, self.builder.next_id()))
1348 }
1349
1350 fn struct_locator_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1352 let span = self.content_span(node);
1353 let id = self.builder.next_id();
1354 let path = self.locator_tokens_to_path(node)?;
1355 self.composite_expression_from_path(node, path, span, id)
1356 }
1357
1358 fn path_locator_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1360 let path = self.locator_tokens_to_path(node)?;
1361 Ok(leo_ast::Expression::Path(path))
1362 }
1363
1364 fn locator_tokens_to_path(&self, node: &SyntaxNode) -> Result<leo_ast::Path> {
1369 let mut idents = tokens(node).filter(|t| t.kind() == IDENT);
1370 let program_token = idents.next().expect("locator should have program IDENT");
1371 let name_token = idents.next().expect("locator should have name IDENT");
1372
1373 let program_ident = self.to_identifier(&program_token);
1375
1376 let kw_aleo_token = tokens(node).find(|t| t.kind() == KW_ALEO).expect("locator should have `aleo` keyword");
1378
1379 let network_ident = leo_ast::Identifier {
1380 name: Symbol::intern("aleo"),
1381 span: self.token_span(&kw_aleo_token),
1382 id: self.builder.next_id(),
1383 };
1384
1385 let program = leo_ast::ProgramId { name: program_ident, network: network_ident };
1387
1388 let name = self.to_identifier(&name_token);
1390 let path_span = Span::new(program.name.span.lo, name.span.hi);
1391
1392 Ok(leo_ast::Path::new(Some(program), Vec::new(), name, path_span, self.builder.next_id()))
1393 }
1394
1395 fn struct_field_init_to_member(&self, node: &SyntaxNode) -> Result<leo_ast::CompositeFieldInitializer> {
1397 debug_assert!(matches!(node.kind(), STRUCT_FIELD_INIT | STRUCT_FIELD_SHORTHAND));
1398 let span = self.content_span(node);
1399 let id = self.builder.next_id();
1400
1401 let Some(ident_token) = tokens(node).find(|t| t.kind() == IDENT) else {
1402 self.emit_unexpected_str("identifier in struct field", node.text(), span);
1403 return Ok(leo_ast::CompositeFieldInitializer {
1404 identifier: self.error_identifier(span),
1405 expression: None,
1406 span,
1407 id,
1408 });
1409 };
1410 let identifier = self.to_identifier(&ident_token);
1411
1412 let expression = if node.kind() == STRUCT_FIELD_INIT {
1413 children(node).find(|n| n.kind().is_expression()).map(|n| self.to_expression(&n)).transpose()?
1414 } else {
1415 None
1416 };
1417
1418 Ok(leo_ast::CompositeFieldInitializer { identifier, expression, span, id })
1419 }
1420
1421 fn program_ref_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1423 debug_assert_eq!(node.kind(), PROGRAM_REF_EXPR);
1424 let span = self.content_span(node);
1425 let id = self.builder.next_id();
1426 let text: String = tokens(node).map(|t| t.text().to_string()).collect();
1427 Ok(leo_ast::Literal::address(text, span, id).into())
1428 }
1429
1430 fn path_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1432 debug_assert_eq!(node.kind(), PATH_EXPR);
1433
1434 let path = self.path_expr_to_path(node)?;
1435 let span = self.trimmed_span(node);
1436 let id = self.builder.next_id();
1437
1438 if path.user_program().is_none()
1440 && path.qualifier().len() == 1
1441 && path.qualifier()[0].name == sym::group
1442 && path.identifier().name == sym::GEN
1443 {
1444 return Ok(self.intrinsic_expression(sym::_group_gen, Vec::new(), span));
1445 }
1446
1447 if path.user_program().is_none() && path.qualifier().is_empty() {
1450 let name_text = path.identifier().name.to_string();
1451 if name_text.starts_with("sign1") && name_text.parse::<Signature<TestnetV0>>().is_ok() {
1452 return Ok(leo_ast::Literal::signature(name_text, span, id).into());
1453 }
1454 if name_text.starts_with('_') {
1457 self.handler.emit_err(ParserError::identifier_cannot_start_with_underscore(span));
1458 return Ok(self.error_expression(span));
1459 }
1460 }
1461
1462 Ok(leo_ast::Expression::Path(path))
1463 }
1464
1465 fn keyword_expr_to_path(&self, node: &SyntaxNode, name: Symbol) -> Result<leo_ast::Expression> {
1467 let span = self.trimmed_span(node);
1468 let ident = leo_ast::Identifier { name, span, id: self.builder.next_id() };
1469 let path = leo_ast::Path::new(None, Vec::new(), ident, span, self.builder.next_id());
1470 Ok(leo_ast::Expression::Path(path))
1471 }
1472
1473 fn final_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1475 debug_assert_eq!(node.kind(), FINAL_EXPR);
1476 let span = self.content_span(node);
1477 let id = self.builder.next_id();
1478
1479 if let Some(block_node) = children(node).find(|n| n.kind() == BLOCK) {
1481 let block = self.to_block(&block_node)?;
1482 Ok(leo_ast::AsyncExpression { block, span, id }.into())
1483 } else {
1484 self.emit_unexpected_str("block in final expression", node.text(), span);
1486 Ok(self.error_expression(span))
1487 }
1488 }
1489
1490 fn path_expr_to_path(&self, node: &SyntaxNode) -> Result<leo_ast::Path> {
1498 let span = self.trimmed_span(node);
1499
1500 let mut path_components = Vec::new();
1502 for token in tokens(node) {
1503 match token.kind() {
1504 IDENT => {
1505 let text = token.text();
1506 if text.contains("::") {
1510 let token_span = self.token_span(&token);
1511 let mut offset = token_span.lo;
1512 for (i, segment) in text.split("::").enumerate() {
1513 if i > 0 {
1514 offset += 2; }
1516 let seg_span = Span::new(offset, offset + segment.len() as u32);
1517 path_components.push(leo_ast::Identifier {
1518 name: Symbol::intern(segment),
1519 span: seg_span,
1520 id: self.builder.next_id(),
1521 });
1522 offset += segment.len() as u32;
1523 }
1524 } else {
1525 path_components.push(self.to_identifier(&token));
1526 }
1527 }
1528 kind => {
1529 if let Some(name) = keyword_to_path_symbol(kind) {
1530 path_components.push(leo_ast::Identifier {
1531 name,
1532 span: self.token_span(&token),
1533 id: self.builder.next_id(),
1534 });
1535 }
1536 }
1537 }
1538 }
1539
1540 let name = match path_components.pop() {
1541 Some(name) => name,
1542 None => {
1543 self.emit_unexpected_str("identifier in path", node.text(), span);
1544 self.error_identifier(span)
1545 }
1546 };
1547 Ok(leo_ast::Path::new(None, path_components, name, span, self.builder.next_id()))
1548 }
1549
1550 fn to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1556 let span = self.to_span(node);
1557 let id = self.builder.next_id();
1558
1559 let stmt = match node.kind() {
1560 LET_STMT => self.let_stmt_to_statement(node)?,
1561 CONST_STMT => self.const_stmt_to_statement(node)?,
1562 RETURN_STMT => self.return_stmt_to_statement(node)?,
1563 EXPR_STMT => self.expr_stmt_to_statement(node)?,
1564 ASSIGN_STMT => self.simple_assign_to_statement(node)?,
1565 COMPOUND_ASSIGN_STMT => self.compound_assign_to_statement(node)?,
1566 IF_STMT => self.if_stmt_to_statement(node)?,
1567 FOR_STMT | FOR_INCLUSIVE_STMT => self.for_stmt_to_statement(node)?,
1568 BLOCK => self.to_block(node)?.into(),
1569 ASSERT_STMT => {
1570 let expression = self.require_expression(node, "expression in assert")?;
1571 leo_ast::AssertStatement { variant: leo_ast::AssertVariant::Assert(expression), span, id }.into()
1572 }
1573 ASSERT_EQ_STMT => {
1574 self.assert_binary_to_statement(node, "assert_eq", span, id, leo_ast::AssertVariant::AssertEq)?
1575 }
1576 ASSERT_NEQ_STMT => {
1577 self.assert_binary_to_statement(node, "assert_neq", span, id, leo_ast::AssertVariant::AssertNeq)?
1578 }
1579 ROOT => {
1581 if let Some(inner) = children(node).find(|n| n.kind().is_statement()) {
1582 self.to_statement(&inner)?
1583 } else {
1584 leo_ast::ExpressionStatement { expression: self.error_expression(span), span, id }.into()
1586 }
1587 }
1588 ERROR => leo_ast::ExpressionStatement { expression: self.error_expression(span), span, id }.into(),
1591 kind => panic!("unexpected statement kind: {:?}", kind),
1592 };
1593
1594 Ok(stmt)
1595 }
1596
1597 fn assert_binary_to_statement(
1599 &self,
1600 node: &SyntaxNode,
1601 label: &str,
1602 span: Span,
1603 id: leo_ast::NodeID,
1604 make_variant: fn(leo_ast::Expression, leo_ast::Expression) -> leo_ast::AssertVariant,
1605 ) -> Result<leo_ast::Statement> {
1606 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1607 let e0 = match exprs.next() {
1608 Some(expr) => self.to_expression(&expr)?,
1609 None => {
1610 self.emit_unexpected_str(&format!("first expression in {label}"), node.text(), span);
1611 self.error_expression(span)
1612 }
1613 };
1614 let e1 = match exprs.next() {
1615 Some(expr) => self.to_expression(&expr)?,
1616 None => {
1617 self.emit_unexpected_str(&format!("second expression in {label}"), node.text(), span);
1618 self.error_expression(span)
1619 }
1620 };
1621 Ok(leo_ast::AssertStatement { variant: make_variant(e0, e1), span, id }.into())
1622 }
1623
1624 fn to_block(&self, node: &SyntaxNode) -> Result<leo_ast::Block> {
1626 debug_assert_eq!(node.kind(), BLOCK);
1627 let span = self.to_span(node);
1628 let id = self.builder.next_id();
1629
1630 let statements = children(node)
1631 .filter(|n| n.kind().is_statement())
1632 .map(|n| self.to_statement(&n))
1633 .collect::<Result<Vec<_>>>()?;
1634
1635 Ok(leo_ast::Block { statements, span, id })
1636 }
1637
1638 fn let_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1640 debug_assert_eq!(node.kind(), LET_STMT);
1641 let span = self.to_span(node);
1642 let id = self.builder.next_id();
1643
1644 let place = match children(node).find(|n| matches!(n.kind(), IDENT_PATTERN | TUPLE_PATTERN | WILDCARD_PATTERN))
1646 {
1647 Some(pattern_node) => self.pattern_to_definition_place(&pattern_node)?,
1648 None => {
1649 self.emit_unexpected_str("pattern in let statement", node.text(), span);
1650 leo_ast::DefinitionPlace::Single(self.error_identifier(span))
1651 }
1652 };
1653
1654 let type_ = children(node).find(|n| n.kind().is_type()).map(|n| self.to_type(&n)).transpose()?;
1656
1657 let value = self.require_expression(node, "value in let statement")?;
1658
1659 Ok(leo_ast::DefinitionStatement { place, type_, value, span, id }.into())
1660 }
1661
1662 fn pattern_to_definition_place(&self, node: &SyntaxNode) -> Result<leo_ast::DefinitionPlace> {
1664 let span = self.to_span(node);
1665 match node.kind() {
1666 IDENT_PATTERN => {
1667 let ident = self.require_ident(node, "identifier in pattern");
1668 self.validate_definition_identifier(&ident);
1669 Ok(leo_ast::DefinitionPlace::Single(ident))
1670 }
1671 TUPLE_PATTERN => {
1672 let names = children(node)
1673 .filter(|n| matches!(n.kind(), IDENT_PATTERN | WILDCARD_PATTERN))
1674 .map(|n| {
1675 if n.kind() == WILDCARD_PATTERN {
1676 let span = self.to_span(&n);
1678 leo_ast::Identifier { name: Symbol::intern("_"), span, id: self.builder.next_id() }
1679 } else {
1680 let ident = self.require_ident(&n, "identifier in pattern");
1681 self.validate_definition_identifier(&ident);
1682 ident
1683 }
1684 })
1685 .collect();
1686 Ok(leo_ast::DefinitionPlace::Multiple(names))
1687 }
1688 WILDCARD_PATTERN => {
1689 let ident = leo_ast::Identifier { name: Symbol::intern("_"), span, id: self.builder.next_id() };
1690 Ok(leo_ast::DefinitionPlace::Single(ident))
1691 }
1692 _ => {
1693 self.emit_unexpected_str("valid pattern", node.text(), span);
1694 let ident = self.error_identifier(span);
1695 Ok(leo_ast::DefinitionPlace::Single(ident))
1696 }
1697 }
1698 }
1699
1700 fn const_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1702 debug_assert_eq!(node.kind(), CONST_STMT);
1703 let span = self.to_span(node);
1704 let id = self.builder.next_id();
1705
1706 let place = self.require_ident(node, "name in const declaration");
1707
1708 let type_ = self.require_type(node, "type in const declaration")?;
1709
1710 let value = self.require_expression(node, "value in const declaration")?;
1711
1712 Ok(leo_ast::ConstDeclaration { place, type_, value, span, id }.into())
1713 }
1714
1715 fn return_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1717 debug_assert_eq!(node.kind(), RETURN_STMT);
1718 let span = self.to_span(node);
1719 let id = self.builder.next_id();
1720
1721 let expression = children(node)
1723 .find(|n| n.kind().is_expression())
1724 .map(|n| self.to_expression(&n))
1725 .transpose()?
1726 .unwrap_or_else(|| leo_ast::UnitExpression { span, id: self.builder.next_id() }.into());
1727
1728 Ok(leo_ast::ReturnStatement { expression, span, id }.into())
1729 }
1730
1731 fn expr_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1733 debug_assert_eq!(node.kind(), EXPR_STMT);
1734 let span = self.to_span(node);
1735 let id = self.builder.next_id();
1736
1737 let expression = self.require_expression(node, "expression in expression statement")?;
1738
1739 Ok(leo_ast::ExpressionStatement { expression, span, id }.into())
1740 }
1741
1742 fn simple_assign_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1744 debug_assert_eq!(node.kind(), ASSIGN_STMT);
1745 let span = self.to_span(node);
1746 let id = self.builder.next_id();
1747
1748 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1749
1750 let place = match exprs.next() {
1751 Some(n) => self.to_expression(&n)?,
1752 None => {
1753 self.emit_unexpected_str("left side in assignment", node.text(), span);
1754 return Ok(leo_ast::ExpressionStatement { expression: self.error_expression(span), span, id }.into());
1755 }
1756 };
1757
1758 let value = match exprs.next() {
1759 Some(n) => self.to_expression(&n)?,
1760 None => {
1761 self.emit_unexpected_str("right side in assignment", node.text(), span);
1762 self.error_expression(span)
1763 }
1764 };
1765
1766 Ok(leo_ast::AssignStatement { place, value, span, id }.into())
1767 }
1768
1769 fn compound_assign_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1773 debug_assert_eq!(node.kind(), COMPOUND_ASSIGN_STMT);
1774 let span = self.to_span(node);
1775 let id = self.builder.next_id();
1776
1777 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1778
1779 let left = match exprs.next() {
1780 Some(n) => self.to_expression(&n)?,
1781 None => {
1782 self.emit_unexpected_str("left side in compound assignment", node.text(), span);
1783 return Ok(leo_ast::ExpressionStatement { expression: self.error_expression(span), span, id }.into());
1784 }
1785 };
1786
1787 let right = match exprs.next() {
1788 Some(n) => self.to_expression(&n)?,
1789 None => {
1790 self.emit_unexpected_str("right side in compound assignment", node.text(), span);
1791 self.error_expression(span)
1792 }
1793 };
1794
1795 let op_token =
1796 tokens(node).find(|t| is_assign_op(t.kind())).expect("COMPOUND_ASSIGN_STMT should have operator");
1797
1798 let binary_op = match op_token.kind() {
1799 PLUS_EQ => leo_ast::BinaryOperation::Add,
1800 MINUS_EQ => leo_ast::BinaryOperation::Sub,
1801 STAR_EQ => leo_ast::BinaryOperation::Mul,
1802 SLASH_EQ => leo_ast::BinaryOperation::Div,
1803 PERCENT_EQ => leo_ast::BinaryOperation::Rem,
1804 STAR2_EQ => leo_ast::BinaryOperation::Pow,
1805 AMP_EQ => leo_ast::BinaryOperation::BitwiseAnd,
1806 PIPE_EQ => leo_ast::BinaryOperation::BitwiseOr,
1807 CARET_EQ => leo_ast::BinaryOperation::Xor,
1808 SHL_EQ => leo_ast::BinaryOperation::Shl,
1809 SHR_EQ => leo_ast::BinaryOperation::Shr,
1810 AMP2_EQ => leo_ast::BinaryOperation::And,
1811 PIPE2_EQ => leo_ast::BinaryOperation::Or,
1812 k => panic!("unexpected compound assignment operator: {k:?}"),
1813 };
1814
1815 let value =
1816 leo_ast::BinaryExpression { left: left.clone(), right, op: binary_op, span, id: self.builder.next_id() }
1817 .into();
1818
1819 Ok(leo_ast::AssignStatement { place: left, value, span, id }.into())
1820 }
1821
1822 fn if_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1824 debug_assert_eq!(node.kind(), IF_STMT);
1825 let span = self.to_span(node);
1826 let id = self.builder.next_id();
1827
1828 let condition = self.require_expression(node, "condition in if statement")?;
1829
1830 let mut block_or_if = children(node).filter(|n| n.kind() == BLOCK || n.kind() == IF_STMT);
1833
1834 let then = match block_or_if.next() {
1835 Some(n) if n.kind() == BLOCK => self.to_block(&n)?,
1836 _ => {
1837 self.emit_unexpected_str("then block in if statement", node.text(), span);
1838 self.error_block(span)
1839 }
1840 };
1841
1842 let otherwise = block_or_if.next().map(|n| self.to_statement(&n)).transpose()?.map(Box::new);
1843
1844 Ok(leo_ast::ConditionalStatement { condition, then, otherwise, span, id }.into())
1845 }
1846
1847 fn for_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1849 debug_assert!(matches!(node.kind(), FOR_STMT | FOR_INCLUSIVE_STMT));
1850 let span = self.to_span(node);
1851 let id = self.builder.next_id();
1852
1853 let variable = self.require_ident(node, "variable in for statement");
1854
1855 let type_ = children(node).find(|n| n.kind().is_type()).map(|n| self.to_type(&n)).transpose()?;
1857
1858 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1860
1861 let start = match exprs.next() {
1862 Some(n) => self.to_expression(&n)?,
1863 None => {
1864 self.emit_unexpected_str("start expression in for statement", node.text(), span);
1865 self.error_expression(span)
1866 }
1867 };
1868
1869 let stop = match exprs.next() {
1870 Some(n) => self.to_expression(&n)?,
1871 None => {
1872 self.emit_unexpected_str("stop expression in for statement", node.text(), span);
1873 self.error_expression(span)
1874 }
1875 };
1876
1877 let block = match children(node).find(|n| n.kind() == BLOCK) {
1879 Some(block_node) => self.to_block(&block_node)?,
1880 None => {
1881 self.emit_unexpected_str("block in for statement", node.text(), span);
1882 self.error_block(span)
1883 }
1884 };
1885
1886 let inclusive = node.kind() == FOR_INCLUSIVE_STMT;
1887
1888 Ok(leo_ast::IterationStatement { variable, type_, start, stop, inclusive, block, span, id }.into())
1889 }
1890
1891 fn collect_program_item(
1897 &self,
1898 item: &SyntaxNode,
1899 is_in_program_block: bool,
1900 functions: &mut Vec<(Symbol, leo_ast::Function)>,
1901 composites: &mut Vec<(Symbol, leo_ast::Composite)>,
1902 consts: &mut Vec<(Symbol, leo_ast::ConstDeclaration)>,
1903 interfaces: &mut Vec<(Symbol, leo_ast::Interface)>,
1904 ) -> Result<()> {
1905 match item.kind() {
1906 FUNCTION_DEF | FINAL_FN_DEF => {
1907 let func = self.to_function(item, is_in_program_block)?;
1908 functions.push((func.identifier.name, func));
1909 }
1910 STRUCT_DEF | RECORD_DEF => {
1911 let composite = self.to_composite(item)?;
1912 composites.push((composite.identifier.name, composite));
1913 }
1914 GLOBAL_CONST => {
1915 let global_const = self.to_global_const(item)?;
1916 consts.push((global_const.place.name, global_const));
1917 }
1918 INTERFACE_DEF => {
1919 let interface = self.to_interface(item)?;
1920 interfaces.push((interface.identifier.name, interface));
1921 }
1922 _ => {}
1923 }
1924 Ok(())
1925 }
1926
1927 fn collect_library_item(
1929 &self,
1930 item: &SyntaxNode,
1931 consts: &mut Vec<(Symbol, leo_ast::ConstDeclaration)>,
1932 structs: &mut Vec<(Symbol, leo_ast::Composite)>,
1933 functions: &mut Vec<(Symbol, leo_ast::Function)>,
1934 ) -> Result<()> {
1935 if is_library_item(item.kind()) {
1936 match item.kind() {
1937 GLOBAL_CONST => {
1938 let global_const = self.to_global_const(item)?;
1939 consts.push((global_const.place.name, global_const));
1940 }
1941 STRUCT_DEF => {
1942 let composite = self.to_composite(item)?;
1943 structs.push((composite.identifier.name, composite));
1944 }
1945 FUNCTION_DEF => {
1946 let func = self.to_function(item, false)?;
1948 functions.push((func.identifier.name, func));
1949 }
1950 _ => {}
1951 }
1952 } else if is_program_item(item.kind()) {
1953 let span = self.to_span(item);
1955 self.handler.emit_err(ParserError::custom(
1956 "Only `const` declarations, `struct` definitions, and `fn` functions are allowed in a library.",
1957 span,
1958 ));
1959 }
1960 Ok(())
1963 }
1964
1965 fn to_module(&self, node: &SyntaxNode, program_name: Symbol, path: Vec<Symbol>) -> Result<leo_ast::Module> {
1967 let mut functions = Vec::new();
1969 let mut composites = Vec::new();
1970 let mut consts = Vec::new();
1971 let mut interfaces = Vec::new();
1972
1973 for child in children(node) {
1974 if child.kind() == PROGRAM_DECL {
1975 for item in children(&child) {
1976 self.collect_program_item(
1977 &item,
1978 true,
1979 &mut functions,
1980 &mut composites,
1981 &mut consts,
1982 &mut interfaces,
1983 )?;
1984 }
1985 } else {
1986 self.collect_program_item(
1987 &child,
1988 false,
1989 &mut functions,
1990 &mut composites,
1991 &mut consts,
1992 &mut interfaces,
1993 )?;
1994 }
1995 }
1996
1997 functions.sort_by_key(|func| if func.1.variant.is_entry() { 0u8 } else { 1u8 });
1999
2000 Ok(leo_ast::Module { program_name, path, consts, composites, functions, interfaces })
2001 }
2002
2003 fn to_main(&self, node: &SyntaxNode) -> Result<leo_ast::Program> {
2005 let mut imports = indexmap::IndexMap::new();
2007 let mut functions = Vec::new();
2008 let mut composites = Vec::new();
2009 let mut consts = Vec::new();
2010 let mut mappings = Vec::new();
2011 let mut storage_variables = Vec::new();
2012 let mut constructors = Vec::new();
2013 let mut interfaces = Vec::new();
2014 let mut program_name = None;
2015 let mut network = None;
2016 let mut parents = Vec::new();
2017 let mut span = None;
2018
2019 for child in children(node) {
2020 match child.kind() {
2021 IMPORT => {
2022 let program_id = self.import_to_program_id(&child)?;
2023 imports.insert(program_id.as_symbol(), program_id);
2024 }
2025 PROGRAM_DECL => {
2026 if program_name.is_some() {
2027 self.handler.emit_err(ParserError::multiple_program_declarations(self.non_trivia_span(&child)));
2028 continue;
2029 }
2030 let (pname, pnetwork, pparents) = self.program_decl_to_name_with_parent(&child)?;
2032 program_name = Some(pname);
2033 network = Some(pnetwork);
2034 parents = pparents;
2035 span = Some(self.to_span(&child));
2036
2037 for item in children(&child) {
2039 self.collect_program_item(
2040 &item,
2041 true,
2042 &mut functions,
2043 &mut composites,
2044 &mut consts,
2045 &mut interfaces,
2046 )?;
2047 match item.kind() {
2048 MAPPING_DEF => {
2049 let mapping = self.to_mapping(&item)?;
2050 mappings.push((mapping.identifier.name, mapping));
2051 }
2052 STORAGE_DEF => {
2053 let storage = self.to_storage(&item)?;
2054 storage_variables.push((storage.identifier.name, storage));
2055 }
2056 CONSTRUCTOR_DEF => {
2057 constructors.push(self.to_constructor(&item)?);
2058 }
2059 _ => {}
2060 }
2061 }
2062 }
2063 _ => {
2064 self.collect_program_item(
2065 &child,
2066 false,
2067 &mut functions,
2068 &mut composites,
2069 &mut consts,
2070 &mut interfaces,
2071 )?;
2072 }
2073 }
2074 }
2075
2076 if let Some(extra) = constructors.get(1) {
2077 return Err(ParserError::custom("A program can only have one constructor.", extra.span).into());
2078 }
2079
2080 let (Some(program_name), Some(network), Some(span)) = (program_name, network, span) else {
2081 return Err(ParserError::missing_program_scope(self.to_span(node)).into());
2082 };
2083
2084 functions.sort_by_key(|func| if func.1.variant.is_entry() { 0u8 } else { 1u8 });
2086
2087 let program_id = leo_ast::ProgramId { name: program_name, network };
2088 let program_id_as_symbol = program_id.as_symbol();
2089 let program_scope = leo_ast::ProgramScope {
2090 program_id,
2091 parents,
2092 consts,
2093 composites,
2094 mappings,
2095 storage_variables,
2096 functions,
2097 interfaces,
2098 constructor: constructors.pop(),
2099 span,
2100 };
2101
2102 Ok(leo_ast::Program {
2103 imports,
2104 modules: indexmap::IndexMap::new(),
2105 stubs: indexmap::IndexMap::new(),
2106 program_scopes: vec![(program_id_as_symbol, program_scope)].into_iter().collect(),
2107 })
2108 }
2109
2110 fn to_library(&self, name: Symbol, node: &SyntaxNode) -> Result<leo_ast::Library> {
2112 let mut consts = Vec::new();
2113 let mut structs = Vec::new();
2114 let mut functions = Vec::new();
2115
2116 for child in children(node) {
2117 self.collect_library_item(&child, &mut consts, &mut structs, &mut functions)?;
2118 }
2119
2120 Ok(leo_ast::Library { name, modules: indexmap::IndexMap::new(), consts, structs, functions })
2121 }
2122
2123 fn import_to_program_id(&self, node: &SyntaxNode) -> Result<leo_ast::ProgramId> {
2125 debug_assert_eq!(node.kind(), IMPORT);
2126 let span = self.to_span(node);
2127
2128 let program_name_text = match tokens(node).find(|t| t.kind() == IDENT) {
2130 Some(name_token) => name_token.text().to_string(),
2131 None => {
2132 self.emit_unexpected_str("import name", node.text(), span);
2133 "_error".to_string()
2134 }
2135 };
2136
2137 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 {
2141 name: leo_ast::Identifier { name: Symbol::intern(&program_name_text), span, id: self.builder.next_id() },
2142 network: leo_ast::Identifier {
2143 name: Symbol::intern("aleo"),
2144 span: network_span,
2145 id: self.builder.next_id(),
2146 },
2147 };
2148
2149 if tokens(node).all(|t| t.kind() != KW_ALEO)
2151 && let Some(net_token) = find_invalid_network(node)
2152 {
2153 self.handler.emit_err(ParserError::invalid_network(self.token_span(&net_token)));
2154 }
2155
2156 Ok(program_id)
2157 }
2158
2159 fn program_decl_to_name(&self, node: &SyntaxNode) -> Result<(leo_ast::Identifier, leo_ast::Identifier)> {
2161 debug_assert_eq!(node.kind(), PROGRAM_DECL);
2162 let span = self.to_span(node);
2163
2164 let program_name = self.require_ident(node, "program name");
2166
2167 let network = match tokens(node).find(|t| t.kind() == KW_ALEO) {
2168 Some(aleo_token) => leo_ast::Identifier {
2169 name: Symbol::intern("aleo"),
2170 span: self.token_span(&aleo_token),
2171 id: self.builder.next_id(),
2172 },
2173 None => {
2174 if let Some(net_token) = find_invalid_network(node) {
2176 self.handler.emit_err(ParserError::invalid_network(self.token_span(&net_token)));
2177 } else {
2178 self.emit_unexpected_str(".aleo network", node.text(), span);
2179 }
2180 leo_ast::Identifier { name: Symbol::intern("aleo"), span, id: self.builder.next_id() }
2181 }
2182 };
2183
2184 Ok((program_name, network))
2185 }
2186
2187 fn program_decl_to_name_with_parent(
2189 &self,
2190 node: &SyntaxNode,
2191 ) -> Result<(leo_ast::Identifier, leo_ast::Identifier, Parents)> {
2192 debug_assert_eq!(node.kind(), PROGRAM_DECL);
2193 let (program_name, network) = self.program_decl_to_name(node)?;
2194
2195 let parents = if let Some(parent_list) = children(node).find(|n| n.kind() == PARENT_LIST) {
2196 self.collect_parent_list(&parent_list)?
2197 } else {
2198 vec![]
2199 };
2200
2201 Ok((program_name, network, parents))
2202 }
2203
2204 fn collect_parent_list(&self, node: &SyntaxNode) -> Result<Parents> {
2205 debug_assert_eq!(node.kind(), PARENT_LIST);
2206 children(node)
2207 .filter(|n| n.kind().is_type())
2208 .map(|n| self.to_type(&n).map(|t| (self.to_span(&n), t)))
2209 .collect::<Result<Vec<_>>>()
2210 }
2211
2212 fn collect_annotations(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::Annotation>> {
2214 children(node).filter(|n| n.kind() == ANNOTATION).map(|n| self.to_annotation(&n)).collect()
2215 }
2216
2217 fn require_block(&self, node: &SyntaxNode, span: Span) -> Result<leo_ast::Block> {
2219 Ok(children(node)
2220 .find(|n| n.kind() == BLOCK)
2221 .map(|n| self.to_block(&n))
2222 .transpose()?
2223 .unwrap_or_else(|| self.error_block(span)))
2224 }
2225
2226 fn to_function(&self, node: &SyntaxNode, is_in_program_block: bool) -> Result<leo_ast::Function> {
2228 debug_assert!(matches!(node.kind(), FUNCTION_DEF | FINAL_FN_DEF | CONSTRUCTOR_DEF));
2229 let span = self.span_including_annotations(node, self.non_trivia_span(node));
2230 let id = self.builder.next_id();
2231
2232 let annotations = self.collect_annotations(node)?;
2233
2234 let variant = if is_in_program_block {
2236 leo_ast::Variant::EntryPoint
2237 } else {
2238 match node.kind() {
2239 FINAL_FN_DEF => leo_ast::Variant::FinalFn,
2240 _ => leo_ast::Variant::Fn,
2241 }
2242 };
2243
2244 let identifier = self.require_ident(node, "function name");
2245 self.validate_identifier(&identifier);
2246
2247 let const_parameters = self.extract_const_parameters(node)?;
2248
2249 let input = children(node)
2251 .find(|n| n.kind() == PARAM_LIST)
2252 .map(|n| self.param_list_to_inputs(&n))
2253 .transpose()?
2254 .unwrap_or_default();
2255
2256 let (output, output_type) = if let Some(return_type_node) = children(node).find(|n| n.kind() == RETURN_TYPE) {
2262 self.return_type_to_outputs(&return_type_node)?
2264 } else if let Some(type_node) = children(node).find(|n| n.kind().is_type()) {
2265 let type_ = self.to_type(&type_node)?;
2267 let (mode, mode_start) = self.return_mode_before(node, &type_node);
2269 let type_span = self.content_span(&type_node);
2270 let output_span = match mode_start {
2271 Some(start) => Span::new(start, type_span.hi),
2272 None => type_span,
2273 };
2274 let output =
2275 vec![leo_ast::Output { mode, type_: type_.clone(), span: output_span, id: self.builder.next_id() }];
2276 (output, type_)
2277 } else {
2278 (Vec::new(), leo_ast::Type::Unit)
2279 };
2280
2281 let block = self.require_block(node, span)?;
2282
2283 Ok(leo_ast::Function {
2284 annotations,
2285 variant,
2286 identifier,
2287 const_parameters,
2288 input,
2289 output,
2290 output_type,
2291 block,
2292 span,
2293 id,
2294 })
2295 }
2296
2297 fn return_mode_before(&self, parent: &SyntaxNode, type_node: &SyntaxNode) -> (leo_ast::Mode, Option<u32>) {
2303 let type_start = type_node.text_range().start();
2304 let mut mode = leo_ast::Mode::None;
2305 let mut mode_start = None;
2306 for token in tokens(parent) {
2307 let token_end = token.text_range().end();
2308 if token_end > type_start {
2309 break;
2310 }
2311 if let Some(m) = token_kind_to_mode(token.kind()) {
2312 mode = m;
2313 mode_start = Some(u32::from(token.text_range().start()) + self.start_pos);
2314 }
2315 }
2316 (mode, mode_start)
2317 }
2318
2319 fn return_type_to_outputs(&self, node: &SyntaxNode) -> Result<(Vec<leo_ast::Output>, leo_ast::Type)> {
2321 debug_assert_eq!(node.kind(), RETURN_TYPE);
2322
2323 let mut outputs = Vec::new();
2326 let mut current_mode = leo_ast::Mode::None;
2327 let mut current_mode_start: Option<u32> = None;
2328
2329 for child in node.children_with_tokens() {
2330 match &child {
2331 SyntaxElement::Token(token) if !token.kind().is_trivia() => {
2332 if let Some(m) = token_kind_to_mode(token.kind()) {
2333 current_mode = m;
2334 current_mode_start = Some(u32::from(token.text_range().start()) + self.start_pos);
2335 }
2336 }
2337 SyntaxElement::Node(child_node) if child_node.kind().is_type() => {
2338 let type_ = self.to_type(child_node)?;
2339 let type_span = self.content_span(child_node);
2340 let output_span = match current_mode_start.take() {
2341 Some(start) => Span::new(start, type_span.hi),
2342 None => type_span,
2343 };
2344 outputs.push(leo_ast::Output {
2345 mode: current_mode,
2346 type_,
2347 span: output_span,
2348 id: self.builder.next_id(),
2349 });
2350 current_mode = leo_ast::Mode::None;
2351 }
2352 _ => {}
2353 }
2354 }
2355
2356 let output_type = match outputs.len() {
2357 0 => leo_ast::Type::Unit,
2358 1 => outputs[0].type_.clone(),
2359 _ => leo_ast::TupleType::new(outputs.iter().map(|o| o.type_.clone()).collect()).into(),
2360 };
2361
2362 Ok((outputs, output_type))
2363 }
2364
2365 fn to_annotation(&self, node: &SyntaxNode) -> Result<leo_ast::Annotation> {
2367 debug_assert_eq!(node.kind(), ANNOTATION);
2368 let span = self.trimmed_span(node);
2369 let id = self.builder.next_id();
2370
2371 let name_token =
2374 tokens(node).find(|t| t.kind() == IDENT || t.kind().is_keyword()).expect("annotation should have name");
2375 let name = Symbol::intern(name_token.text());
2376 let name_span = self.token_span(&name_token);
2377 let identifier = leo_ast::Identifier { name, span: name_span, id: self.builder.next_id() };
2378
2379 let map = children(node)
2381 .filter(|n| n.kind() == ANNOTATION_PAIR)
2382 .filter_map(|pair| {
2383 let key =
2384 tokens(&pair).find(|t| t.kind() == IDENT || t.kind() == KW_ADDRESS || t.kind() == KW_MAPPING)?;
2385 let val = tokens(&pair).find(|t| t.kind() == STRING)?;
2386 let text = val.text();
2387 Some((Symbol::intern(key.text()), text[1..text.len() - 1].to_string()))
2388 })
2389 .collect();
2390
2391 Ok(leo_ast::Annotation { identifier, map, span, id })
2392 }
2393
2394 fn param_list_to_inputs(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::Input>> {
2396 debug_assert_eq!(node.kind(), PARAM_LIST);
2397
2398 children(node)
2399 .filter(|n| matches!(n.kind(), PARAM | PARAM_PUBLIC | PARAM_PRIVATE | PARAM_CONSTANT))
2400 .map(|n| self.param_to_input(&n))
2401 .collect()
2402 }
2403
2404 fn param_to_input(&self, node: &SyntaxNode) -> Result<leo_ast::Input> {
2406 debug_assert!(matches!(node.kind(), PARAM | PARAM_PUBLIC | PARAM_PRIVATE | PARAM_CONSTANT));
2407 let span = self.non_trivia_span(node);
2408 let id = self.builder.next_id();
2409
2410 let mode = node_kind_to_mode(node.kind());
2411
2412 let identifier = self.require_ident(node, "parameter name");
2413 self.validate_identifier(&identifier);
2414
2415 let type_ = self.require_type(node, "parameter type")?;
2416
2417 Ok(leo_ast::Input { identifier, mode, type_, span, id })
2418 }
2419
2420 fn to_const_parameters(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::ConstParameter>> {
2422 debug_assert_eq!(node.kind(), CONST_PARAM_LIST);
2423
2424 children(node)
2425 .filter(|n| n.kind() == CONST_PARAM)
2426 .map(|n| {
2427 let span = self.non_trivia_span(&n);
2428 let id = self.builder.next_id();
2429
2430 let identifier = self.require_ident(&n, "const parameter name");
2431
2432 let type_ = self.require_type(&n, "const parameter type")?;
2433
2434 Ok(leo_ast::ConstParameter { identifier, type_, span, id })
2435 })
2436 .collect()
2437 }
2438
2439 fn extract_const_parameters(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::ConstParameter>> {
2441 children(node)
2442 .find(|n| n.kind() == CONST_PARAM_LIST)
2443 .map(|n| self.to_const_parameters(&n))
2444 .transpose()
2445 .map(|opt| opt.unwrap_or_default())
2446 }
2447
2448 fn to_composite(&self, node: &SyntaxNode) -> Result<leo_ast::Composite> {
2450 debug_assert!(matches!(node.kind(), STRUCT_DEF | RECORD_DEF));
2451 let span = self.non_trivia_span(node);
2452 let id = self.builder.next_id();
2453
2454 let is_record = node.kind() == RECORD_DEF;
2455
2456 let identifier = self.require_ident(node, "struct/record name");
2457 self.validate_identifier(&identifier);
2458
2459 let const_parameters = self.extract_const_parameters(node)?;
2460
2461 let members = children(node)
2463 .filter(|n| {
2464 matches!(
2465 n.kind(),
2466 STRUCT_MEMBER | STRUCT_MEMBER_PUBLIC | STRUCT_MEMBER_PRIVATE | STRUCT_MEMBER_CONSTANT
2467 )
2468 })
2469 .map(|n| self.struct_member_to_member(&n))
2470 .collect::<Result<Vec<_>>>()?;
2471
2472 Ok(leo_ast::Composite { identifier, const_parameters, members, is_record, span, id })
2473 }
2474
2475 fn struct_member_to_member(&self, node: &SyntaxNode) -> Result<leo_ast::Member> {
2477 debug_assert!(matches!(
2478 node.kind(),
2479 STRUCT_MEMBER | STRUCT_MEMBER_PUBLIC | STRUCT_MEMBER_PRIVATE | STRUCT_MEMBER_CONSTANT
2480 ));
2481 let span = self.non_trivia_span(node);
2482 let id = self.builder.next_id();
2483
2484 let mode = node_kind_to_mode(node.kind());
2485
2486 let identifier = self.require_ident(node, "member name");
2487 self.validate_identifier(&identifier);
2488
2489 let type_ = self.require_type(node, "member type")?;
2490
2491 Ok(leo_ast::Member { mode, identifier, type_, span, id })
2492 }
2493
2494 fn to_global_const(&self, node: &SyntaxNode) -> Result<leo_ast::ConstDeclaration> {
2496 debug_assert_eq!(node.kind(), GLOBAL_CONST);
2497 let span = self.non_trivia_span(node);
2498 let id = self.builder.next_id();
2499
2500 let place = self.require_ident(node, "const name");
2501 self.validate_definition_identifier(&place);
2502
2503 let type_ = self.require_type(node, "const type")?;
2504
2505 let value = self.require_expression(node, "const value")?;
2506
2507 Ok(leo_ast::ConstDeclaration { place, type_, value, span, id })
2508 }
2509
2510 fn to_mapping(&self, node: &SyntaxNode) -> Result<leo_ast::Mapping> {
2512 debug_assert_eq!(node.kind(), MAPPING_DEF);
2513 let span = self.non_trivia_span(node);
2514 let id = self.builder.next_id();
2515
2516 let identifier = self.require_ident(node, "name in mapping");
2517
2518 let mut type_nodes = children(node).filter(|n| n.kind().is_type());
2520
2521 let key_type = match type_nodes.next() {
2522 Some(key_node) => self.to_type(&key_node)?,
2523 None => {
2524 self.emit_unexpected_str("key type in mapping", node.text(), span);
2525 leo_ast::Type::Err
2526 }
2527 };
2528
2529 let value_type = match type_nodes.next() {
2530 Some(value_node) => self.to_type(&value_node)?,
2531 None => {
2532 self.emit_unexpected_str("value type in mapping", node.text(), span);
2533 leo_ast::Type::Err
2534 }
2535 };
2536
2537 Ok(leo_ast::Mapping { identifier, key_type, value_type, span, id })
2538 }
2539
2540 fn to_storage(&self, node: &SyntaxNode) -> Result<leo_ast::StorageVariable> {
2542 debug_assert_eq!(node.kind(), STORAGE_DEF);
2543 let span = self.non_trivia_span(node);
2544 let id = self.builder.next_id();
2545
2546 let name = self.require_ident(node, "name in storage");
2547
2548 let type_ = self.require_type(node, "type in storage")?;
2549
2550 Ok(leo_ast::StorageVariable { identifier: name, type_, span, id })
2551 }
2552
2553 fn to_constructor(&self, node: &SyntaxNode) -> Result<leo_ast::Constructor> {
2555 debug_assert_eq!(node.kind(), CONSTRUCTOR_DEF);
2556 let span = self.span_including_annotations(node, self.non_trivia_span(node));
2557 let id = self.builder.next_id();
2558
2559 let annotations = self.collect_annotations(node)?;
2560 let block = self.require_block(node, span)?;
2561
2562 Ok(leo_ast::Constructor { annotations, block, span, id })
2563 }
2564
2565 fn to_interface(&self, node: &SyntaxNode) -> Result<leo_ast::Interface> {
2571 debug_assert_eq!(node.kind(), INTERFACE_DEF);
2572 let span = self.to_span(node);
2573
2574 let identifier = self.require_ident(node, "interface name");
2576
2577 let parents = if let Some(parent_list) = children(node).find(|n| n.kind() == PARENT_LIST) {
2580 self.collect_parent_list(&parent_list)?
2581 } else {
2582 vec![]
2583 };
2584
2585 let mut functions = Vec::new();
2586 let mut records = Vec::new();
2587 let mut mappings = Vec::new();
2588 let mut storages = Vec::new();
2589
2590 for child in children(node) {
2591 match child.kind() {
2592 FN_PROTOTYPE_DEF => {
2593 let proto = self.to_function_prototype(&child)?;
2594 functions.push((proto.identifier.name, proto));
2595 }
2596 RECORD_PROTOTYPE_DEF => {
2597 let proto = self.to_record_prototype(&child)?;
2598 records.push((proto.identifier.name, proto));
2599 }
2600 MAPPING_DEF => {
2601 let mapping = self.to_mapping(&child)?;
2602 mappings.push(mapping);
2603 }
2604 STORAGE_DEF => {
2605 let storage = self.to_storage(&child)?;
2606 storages.push(storage);
2607 }
2608 _ => {}
2609 }
2610 }
2611
2612 Ok(leo_ast::Interface {
2613 identifier,
2614 parents,
2615 span,
2616 id: self.builder.next_id(),
2617 functions,
2618 records,
2619 mappings,
2620 storages,
2621 })
2622 }
2623
2624 fn to_function_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::FunctionPrototype> {
2626 debug_assert_eq!(node.kind(), FN_PROTOTYPE_DEF);
2627 let span = self.to_span(node);
2628
2629 let identifier = self.require_ident(node, "function name");
2630
2631 let const_parameters = self.extract_const_parameters(node)?;
2633
2634 let input = children(node)
2636 .find(|n| n.kind() == PARAM_LIST)
2637 .map(|n| self.param_list_to_inputs(&n))
2638 .transpose()?
2639 .unwrap_or_default();
2640
2641 let output = if let Some(return_type_node) = children(node).find(|n| n.kind() == RETURN_TYPE) {
2644 self.return_type_to_outputs(&return_type_node)?.0
2646 } else if let Some(type_node) = children(node).find(|n| n.kind().is_type()) {
2647 let type_ = self.to_type(&type_node)?;
2649 let (mode, mode_start) = self.return_mode_before(node, &type_node);
2651 let type_span = self.content_span(&type_node);
2652 let output_span = match mode_start {
2653 Some(start) => Span::new(start, type_span.hi),
2654 None => type_span,
2655 };
2656 vec![leo_ast::Output { mode, type_, span: output_span, id: self.builder.next_id() }]
2657 } else {
2658 Vec::new()
2659 };
2660
2661 Ok(leo_ast::FunctionPrototype::new(
2662 vec![], identifier,
2664 const_parameters,
2665 input,
2666 output,
2667 span,
2668 self.builder.next_id(),
2669 ))
2670 }
2671
2672 fn to_record_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::RecordPrototype> {
2674 debug_assert_eq!(node.kind(), RECORD_PROTOTYPE_DEF);
2675
2676 let span = self.to_span(node);
2677 let identifier = self.require_ident(node, "record name");
2678 let members = children(node)
2679 .filter(|n| {
2680 matches!(
2681 n.kind(),
2682 STRUCT_MEMBER | STRUCT_MEMBER_PUBLIC | STRUCT_MEMBER_PRIVATE | STRUCT_MEMBER_CONSTANT
2683 )
2684 })
2685 .map(|n| self.struct_member_to_member(&n))
2686 .collect::<Result<Vec<_>>>()?;
2687
2688 let is_redundant = members.is_empty()
2690 || members.iter().all(|m| {
2691 m.identifier.name == sym::owner && m.type_ == leo_ast::Type::Address && m.mode == leo_ast::Mode::None
2692 });
2693 if is_redundant && !members.is_empty() {
2694 self.handler.emit_warning(ParserWarning::record_prototype_redundant(identifier.name, span));
2696 return Ok(leo_ast::RecordPrototype { identifier, span, members: Vec::new(), id: self.builder.next_id() });
2697 } else if is_redundant {
2698 let had_braces = node.children_with_tokens().any(|c| c.kind() == L_BRACE);
2701 if had_braces {
2702 self.handler.emit_warning(ParserWarning::record_prototype_redundant(identifier.name, span));
2703 }
2704 }
2705
2706 Ok(leo_ast::RecordPrototype { identifier, span, members, id: self.builder.next_id() })
2707 }
2708}
2709
2710fn clamped_span(range: TextRange, start_pos: u32, source_len: u32) -> Span {
2716 let end = start_pos + source_len;
2717 let lo = (u32::from(range.start()) + start_pos).min(end);
2718 let hi = (u32::from(range.end()) + start_pos).min(end).max(lo);
2719 Span::new(lo, hi)
2720}
2721
2722fn emit_lex_errors(handler: &Handler, lex_errors: &[leo_parser_rowan::LexError], start_pos: u32, source_len: u32) {
2724 use leo_parser_rowan::LexErrorKind;
2725 for error in lex_errors {
2726 let span = clamped_span(error.range, start_pos, source_len);
2727
2728 match &error.kind {
2729 LexErrorKind::InvalidDigit { digit, radix, token } => {
2730 handler.emit_err(ParserError::wrong_digit_for_radix_span(*digit, *radix, token, span));
2731 }
2732 LexErrorKind::CouldNotLex { content } => {
2733 handler.emit_err(ParserError::could_not_lex_span(content, span));
2734 }
2735 LexErrorKind::BidiOverride => {
2736 handler.emit_err(ParserError::lexer_bidi_override_span(span));
2737 }
2738 }
2739 }
2740}
2741
2742fn emit_parse_errors(
2745 handler: &Handler,
2746 errors: &[leo_parser_rowan::ParseError],
2747 start_pos: u32,
2748 source_len: u32,
2749 lex_errors: &[leo_parser_rowan::LexError],
2750) {
2751 use std::collections::HashSet;
2752
2753 let has_lex_errors = !lex_errors.is_empty();
2754
2755 let lex_ranges: Vec<(u32, u32)> = lex_errors
2757 .iter()
2758 .map(|e| {
2759 let lo = u32::from(e.range.start()).saturating_add(start_pos);
2760 let hi = u32::from(e.range.end()).saturating_add(start_pos);
2761 (lo, hi)
2762 })
2763 .collect();
2764
2765 let mut emitted_ranges: HashSet<(u32, u32)> = HashSet::new();
2767 let mut count = 0;
2768 let max_errors = 10;
2769
2770 for error in errors {
2771 if count >= max_errors {
2772 break;
2773 }
2774
2775 let span = clamped_span(error.range, start_pos, source_len);
2776 let range_key = (span.lo, span.hi);
2777
2778 if emitted_ranges.contains(&range_key) {
2780 continue;
2781 }
2782
2783 if has_lex_errors && span.lo == span.hi && span.hi == start_pos + source_len {
2786 continue;
2787 }
2788
2789 if lex_ranges.iter().any(|&(lo, hi)| span.lo < hi && span.hi > lo) {
2792 continue;
2793 }
2794
2795 emitted_ranges.insert(range_key);
2796
2797 let is_eof_error = match &error.found {
2800 Some(f) => f.is_empty() || f == "end of file",
2801 None => false,
2802 } || (span.lo == span.hi && span.hi >= start_pos + source_len);
2803
2804 if is_eof_error {
2805 handler.emit_err(ParserError::unexpected_eof(span));
2806 count += 1;
2807 continue;
2808 }
2809
2810 if let Some(found) = &error.found {
2812 if error.expected.is_empty() {
2813 handler.emit_err(ParserError::custom(&error.message, span));
2816 } else {
2817 let expected_str = error.expected.join(", ");
2818 handler.emit_err(ParserError::unexpected(found, expected_str, span));
2819 }
2820 count += 1;
2821 continue;
2822 }
2823
2824 handler.emit_err(ParserError::custom(&error.message, span));
2826 count += 1;
2827 }
2828}
2829
2830fn conversion_context<'a>(
2832 handler: &'a Handler,
2833 node_builder: &'a NodeBuilder,
2834 lex_errors: &[leo_parser_rowan::LexError],
2835 parse_errors: &[leo_parser_rowan::ParseError],
2836 start_pos: u32,
2837 source_len: u32,
2838) -> ConversionContext<'a> {
2839 emit_lex_errors(handler, lex_errors, start_pos, source_len);
2840 emit_parse_errors(handler, parse_errors, start_pos, source_len, lex_errors);
2841 let has_errors = !parse_errors.is_empty() || !lex_errors.is_empty();
2842 ConversionContext::new(handler, node_builder, start_pos, has_errors)
2843}
2844
2845pub fn parse_expression(
2847 handler: Handler,
2848 node_builder: &NodeBuilder,
2849 source: &str,
2850 start_pos: u32,
2851 _network: NetworkName,
2852) -> Result<leo_ast::Expression> {
2853 let parse = leo_parser_rowan::parse_expression_entry(source);
2854 let ctx =
2855 conversion_context(&handler, node_builder, parse.lex_errors(), parse.errors(), start_pos, source.len() as u32);
2856 ctx.to_expression(&parse.syntax())
2857}
2858
2859pub fn parse_statement(
2861 handler: Handler,
2862 node_builder: &NodeBuilder,
2863 source: &str,
2864 start_pos: u32,
2865 _network: NetworkName,
2866) -> Result<leo_ast::Statement> {
2867 let parse = leo_parser_rowan::parse_statement_entry(source);
2868 let ctx =
2869 conversion_context(&handler, node_builder, parse.lex_errors(), parse.errors(), start_pos, source.len() as u32);
2870 ctx.to_statement(&parse.syntax())
2871}
2872
2873pub fn parse_module(
2875 handler: Handler,
2876 node_builder: &NodeBuilder,
2877 source: &str,
2878 start_pos: u32,
2879 program_name: Symbol,
2880 path: Vec<Symbol>,
2881 _network: NetworkName,
2882) -> Result<leo_ast::Module> {
2883 let parse = leo_parser_rowan::parse_module_entry(source);
2884 let ctx =
2885 conversion_context(&handler, node_builder, parse.lex_errors(), parse.errors(), start_pos, source.len() as u32);
2886 ctx.to_module(&parse.syntax(), program_name, path)
2887}
2888
2889pub fn parse_program(
2891 handler: Handler,
2892 node_builder: &NodeBuilder,
2893 source: &SourceFile,
2894 modules: &[std::rc::Rc<SourceFile>],
2895 _network: NetworkName,
2896) -> Result<leo_ast::Program> {
2897 let parse = leo_parser_rowan::parse_file(&source.src);
2899 let main_context = conversion_context(
2900 &handler,
2901 node_builder,
2902 parse.lex_errors(),
2903 parse.errors(),
2904 source.absolute_start,
2905 source.src.len() as u32,
2906 );
2907 let mut program = main_context.to_main(&parse.syntax())?;
2908 let program_name = *program.program_scopes.first().unwrap().0;
2909
2910 let root_dir = match &source.name {
2912 FileName::Real(path) => path.parent().map(|p| p.to_path_buf()),
2913 _ => None,
2914 };
2915
2916 for module in modules {
2917 let module_parse = leo_parser_rowan::parse_module_entry(&module.src);
2918 let module_context = conversion_context(
2919 &handler,
2920 node_builder,
2921 module_parse.lex_errors(),
2922 module_parse.errors(),
2923 module.absolute_start,
2924 module.src.len() as u32,
2925 );
2926
2927 if let Some(key) = compute_module_key(&module.name, root_dir.as_deref()) {
2928 for segment in &key {
2929 if symbol_is_keyword(*segment) {
2930 return Err(ParserError::keyword_used_as_module_name(key.iter().format("::"), segment).into());
2931 }
2932 }
2933 let module_ast = module_context.to_module(&module_parse.syntax(), program_name, key.clone())?;
2934 program.modules.insert(key, module_ast);
2935 }
2936 }
2937
2938 Ok(program)
2939}
2940
2941pub fn parse_library(
2943 handler: Handler,
2944 node_builder: &NodeBuilder,
2945 library_name: Symbol,
2946 source: &SourceFile,
2947 modules: &[std::rc::Rc<SourceFile>],
2948 _network: NetworkName,
2949) -> Result<leo_ast::Library> {
2950 let parse = leo_parser_rowan::parse_file(&source.src);
2952 let main_context = conversion_context(
2953 &handler,
2954 node_builder,
2955 parse.lex_errors(),
2956 parse.errors(),
2957 source.absolute_start,
2958 source.src.len() as u32,
2959 );
2960
2961 let mut library = main_context.to_library(library_name, &parse.syntax())?;
2962
2963 let root_dir = match &source.name {
2965 FileName::Real(path) => path.parent().map(|p| p.to_path_buf()),
2966 _ => None,
2967 };
2968
2969 for module_sf in modules {
2971 let module_parse = leo_parser_rowan::parse_module_entry(&module_sf.src);
2972 let module_context = conversion_context(
2973 &handler,
2974 node_builder,
2975 module_parse.lex_errors(),
2976 module_parse.errors(),
2977 module_sf.absolute_start,
2978 module_sf.src.len() as u32,
2979 );
2980
2981 if let Some(key) = compute_module_key(&module_sf.name, root_dir.as_deref()) {
2982 for segment in &key {
2983 if symbol_is_keyword(*segment) {
2984 return Err(ParserError::keyword_used_as_module_name(key.iter().format("::"), segment).into());
2985 }
2986 }
2987 let module_ast = module_context.to_module(&module_parse.syntax(), library_name, key.clone())?;
2990 library.modules.insert(key, module_ast);
2991 }
2992 }
2993
2994 Ok(library)
2995}
2996
2997fn children(node: &SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ {
3003 node.children().filter(|n| !n.kind().is_trivia())
3004}
3005
3006fn tokens(node: &SyntaxNode) -> impl Iterator<Item = SyntaxToken> + '_ {
3008 node.children_with_tokens().filter_map(|elem| elem.into_token()).filter(|t| !t.kind().is_trivia())
3009}
3010
3011fn find_name_after_dot(node: &SyntaxNode) -> Option<SyntaxToken> {
3013 let dot_end = tokens(node).find(|t| t.kind() == DOT)?.text_range().end();
3014 tokens(node).filter(|t| t.text_range().start() >= dot_end).find(|t| t.kind() == IDENT || t.kind().is_keyword())
3015}
3016
3017fn first_non_trivia_token(node: &SyntaxNode) -> Option<SyntaxToken> {
3019 node.children_with_tokens().find_map(|e| e.into_token().filter(|t| !t.kind().is_trivia()))
3020}
3021
3022fn last_non_trivia_token(node: &SyntaxNode) -> Option<SyntaxToken> {
3024 node.children_with_tokens().filter_map(|e| e.into_token().filter(|t| !t.kind().is_trivia())).last()
3025}
3026
3027fn find_invalid_network(node: &SyntaxNode) -> Option<SyntaxToken> {
3029 let mut saw_dot = false;
3030 tokens(node).find(|t| {
3031 if t.kind() == DOT {
3032 saw_dot = true;
3033 return false;
3034 }
3035 saw_dot && t.kind() == IDENT
3036 })
3037}
3038
3039fn token_kind_to_mode(kind: SyntaxKind) -> Option<leo_ast::Mode> {
3041 match kind {
3042 KW_PUBLIC => Some(leo_ast::Mode::Public),
3043 KW_PRIVATE => Some(leo_ast::Mode::Private),
3044 KW_CONSTANT => Some(leo_ast::Mode::Constant),
3045 _ => None,
3046 }
3047}
3048
3049fn node_kind_to_mode(kind: SyntaxKind) -> leo_ast::Mode {
3051 match kind {
3052 PARAM_PUBLIC | STRUCT_MEMBER_PUBLIC => leo_ast::Mode::Public,
3053 PARAM_PRIVATE | STRUCT_MEMBER_PRIVATE => leo_ast::Mode::Private,
3054 PARAM_CONSTANT | STRUCT_MEMBER_CONSTANT => leo_ast::Mode::Constant,
3055 _ => leo_ast::Mode::None,
3056 }
3057}
3058
3059fn keyword_to_path_symbol(kind: SyntaxKind) -> Option<Symbol> {
3061 match kind {
3062 KW_SELF => Some(sym::SelfLower),
3063 KW_BLOCK => Some(sym::block),
3064 KW_NETWORK => Some(sym::network),
3065 KW_FINAL_UPPER => Some(sym::Final),
3066 _ => None,
3067 }
3068}
3069
3070fn is_assign_op(kind: SyntaxKind) -> bool {
3072 matches!(
3073 kind,
3074 EQ | PLUS_EQ
3075 | MINUS_EQ
3076 | STAR_EQ
3077 | SLASH_EQ
3078 | PERCENT_EQ
3079 | STAR2_EQ
3080 | AMP_EQ
3081 | PIPE_EQ
3082 | CARET_EQ
3083 | SHL_EQ
3084 | SHR_EQ
3085 | AMP2_EQ
3086 | PIPE2_EQ
3087 )
3088}
3089
3090fn keyword_to_primitive_type(kind: SyntaxKind) -> Option<leo_ast::Type> {
3092 let ty = match kind {
3093 KW_ADDRESS => leo_ast::Type::Address,
3094 KW_BOOL => leo_ast::Type::Boolean,
3095 KW_FIELD => leo_ast::Type::Field,
3096 KW_GROUP => leo_ast::Type::Group,
3097 KW_SCALAR => leo_ast::Type::Scalar,
3098 KW_SIGNATURE => leo_ast::Type::Signature,
3099 KW_STRING => leo_ast::Type::String,
3100 KW_DYN => leo_ast::Type::DynRecord,
3101 KW_IDENTIFIER => leo_ast::Type::Identifier,
3102 KW_U8 => leo_ast::Type::Integer(leo_ast::IntegerType::U8),
3103 KW_U16 => leo_ast::Type::Integer(leo_ast::IntegerType::U16),
3104 KW_U32 => leo_ast::Type::Integer(leo_ast::IntegerType::U32),
3105 KW_U64 => leo_ast::Type::Integer(leo_ast::IntegerType::U64),
3106 KW_U128 => leo_ast::Type::Integer(leo_ast::IntegerType::U128),
3107 KW_I8 => leo_ast::Type::Integer(leo_ast::IntegerType::I8),
3108 KW_I16 => leo_ast::Type::Integer(leo_ast::IntegerType::I16),
3109 KW_I32 => leo_ast::Type::Integer(leo_ast::IntegerType::I32),
3110 KW_I64 => leo_ast::Type::Integer(leo_ast::IntegerType::I64),
3111 KW_I128 => leo_ast::Type::Integer(leo_ast::IntegerType::I128),
3112 _ => return None,
3113 };
3114 Some(ty)
3115}
3116
3117fn token_to_binary_op(kind: SyntaxKind) -> leo_ast::BinaryOperation {
3119 match kind {
3120 EQ2 => leo_ast::BinaryOperation::Eq,
3121 BANG_EQ => leo_ast::BinaryOperation::Neq,
3122 LT => leo_ast::BinaryOperation::Lt,
3123 LT_EQ => leo_ast::BinaryOperation::Lte,
3124 GT => leo_ast::BinaryOperation::Gt,
3125 GT_EQ => leo_ast::BinaryOperation::Gte,
3126 PLUS => leo_ast::BinaryOperation::Add,
3127 MINUS => leo_ast::BinaryOperation::Sub,
3128 STAR => leo_ast::BinaryOperation::Mul,
3129 SLASH => leo_ast::BinaryOperation::Div,
3130 PERCENT => leo_ast::BinaryOperation::Rem,
3131 PIPE2 => leo_ast::BinaryOperation::Or,
3132 AMP2 => leo_ast::BinaryOperation::And,
3133 PIPE => leo_ast::BinaryOperation::BitwiseOr,
3134 AMP => leo_ast::BinaryOperation::BitwiseAnd,
3135 STAR2 => leo_ast::BinaryOperation::Pow,
3136 SHL => leo_ast::BinaryOperation::Shl,
3137 SHR => leo_ast::BinaryOperation::Shr,
3138 CARET => leo_ast::BinaryOperation::Xor,
3139 _ => panic!("unexpected binary operator: {:?}", kind),
3140 }
3141}
3142
3143fn symbol_is_keyword(symbol: Symbol) -> bool {
3144 matches!(
3145 symbol,
3146 sym::address
3147 | sym::aleo
3148 | sym::As
3149 | sym::assert
3150 | sym::assert_eq
3151 | sym::assert_neq
3152 | sym::block
3153 | sym::bool
3154 | sym::Const
3155 | sym::constant
3156 | sym::constructor
3157 | sym::Else
3158 | sym::False
3159 | sym::field
3160 | sym::FnUpper
3161 | sym::Fn
3162 | sym::For
3163 | sym::Final
3164 | sym::group
3165 | sym::i8
3166 | sym::i16
3167 | sym::i32
3168 | sym::i64
3169 | sym::i128
3170 | sym::If
3171 | sym::import
3172 | sym::In
3173 | sym::inline
3174 | sym::Let
3175 | sym::leo
3176 | sym::mapping
3177 | sym::storage
3178 | sym::network
3179 | sym::private
3180 | sym::program
3181 | sym::public
3182 | sym::record
3183 | sym::Return
3184 | sym::scalar
3185 | sym::script
3186 | sym::SelfLower
3187 | sym::signature
3188 | sym::string
3189 | sym::Struct
3190 | sym::True
3191 | sym::u8
3192 | sym::u16
3193 | sym::u32
3194 | sym::u64
3195 | sym::u128
3196 )
3197}
3198
3199fn compute_module_key(name: &FileName, root_dir: Option<&std::path::Path>) -> Option<Vec<Symbol>> {
3201 let path = match name {
3202 FileName::Custom(name) => std::path::Path::new(name).to_path_buf(),
3203 FileName::Real(path) => {
3204 let root = root_dir?;
3205 path.strip_prefix(root).ok()?.to_path_buf()
3206 }
3207 };
3208
3209 let mut key: Vec<Symbol> =
3210 path.components().map(|comp| Symbol::intern(&comp.as_os_str().to_string_lossy())).collect();
3211
3212 if let Some(last) = path.file_name()
3213 && let Some(stem) = std::path::Path::new(last).file_stem()
3214 {
3215 key.pop();
3216 key.push(Symbol::intern(&stem.to_string_lossy()));
3217 }
3218
3219 Some(key)
3220}
3221
3222fn is_library_item(kind: SyntaxKind) -> bool {
3227 matches!(kind, GLOBAL_CONST | STRUCT_DEF | FUNCTION_DEF)
3228}
3229
3230fn is_program_item(kind: SyntaxKind) -> bool {
3232 matches!(
3233 kind,
3234 GLOBAL_CONST
3235 | FUNCTION_DEF
3236 | FINAL_FN_DEF
3237 | STRUCT_DEF
3238 | RECORD_DEF
3239 | INTERFACE_DEF
3240 | MAPPING_DEF
3241 | STORAGE_DEF
3242 | CONSTRUCTOR_DEF
3243 | PROGRAM_DECL
3244 | IMPORT
3245 )
3246}