1use itertools::Itertools as _;
31use snarkvm::prelude::{Address, Signature, TestnetV0};
32
33use leo_ast::{NetworkName, NodeBuilder, NodeID};
34use leo_errors::{Handler, ParserError, ParserWarning, Result};
35use leo_parser_rowan::{SyntaxElement, SyntaxKind, SyntaxKind::*, SyntaxNode, SyntaxToken, TextRange};
36use leo_span::{
37 Span,
38 Symbol,
39 source_map::{FileName, SourceFile},
40 sym,
41};
42
43type ConstArgList = (Vec<(leo_ast::Type, Span)>, Vec<leo_ast::Expression>);
45
46type AnnotatedTypes = Vec<(leo_ast::Mode, leo_ast::Type, Span)>;
48
49type Parents = Vec<(Span, leo_ast::Type)>;
51
52struct ConversionContext<'a> {
58 handler: &'a Handler,
59 builder: &'a NodeBuilder,
60 start_pos: u32,
62 suppress_cascade: bool,
68}
69
70impl<'a> ConversionContext<'a> {
71 fn new(handler: &'a Handler, builder: &'a NodeBuilder, start_pos: u32, suppress_cascade: bool) -> Self {
73 Self { handler, builder, start_pos, suppress_cascade }
74 }
75
76 fn emit_unexpected_str(&self, expected: &str, found: impl std::fmt::Display, span: Span) {
78 if !self.suppress_cascade {
79 self.handler.emit_err(ParserError::unexpected_str(expected, found, span));
80 }
81 }
82
83 fn to_span(&self, node: &SyntaxNode) -> Span {
89 let range = node.text_range();
90 Span::new(u32::from(range.start()) + self.start_pos, u32::from(range.end()) + self.start_pos)
91 }
92
93 fn token_span(&self, token: &SyntaxToken) -> Span {
95 let range = token.text_range();
96 Span::new(u32::from(range.start()) + self.start_pos, u32::from(range.end()) + self.start_pos)
97 }
98
99 fn non_trivia_span(&self, node: &SyntaxNode) -> Span {
102 let start = first_non_trivia_token(node).map(|t| t.text_range().start()).unwrap_or(node.text_range().start());
103 let end = node.text_range().end();
104 Span::new(u32::from(start) + self.start_pos, u32::from(end) + self.start_pos)
105 }
106
107 fn trimmed_span(&self, node: &SyntaxNode) -> Span {
111 let start = first_non_trivia_token(node).map(|t| t.text_range().start()).unwrap_or(node.text_range().start());
112 let end = last_non_trivia_token(node).map(|t| t.text_range().end()).unwrap_or(node.text_range().end());
113 Span::new(u32::from(start) + self.start_pos, u32::from(end) + self.start_pos)
114 }
115
116 fn content_span(&self, node: &SyntaxNode) -> Span {
120 let mut first = node.text_range().start();
121 let mut last = node.text_range().end();
122 let mut found_first = false;
123 for elem in node.descendants_with_tokens() {
124 if let Some(t) = elem.as_token()
125 && !t.kind().is_trivia()
126 {
127 if !found_first {
128 first = t.text_range().start();
129 found_first = true;
130 }
131 last = t.text_range().end();
132 }
133 }
134 Span::new(u32::from(first) + self.start_pos, u32::from(last) + self.start_pos)
135 }
136
137 fn span_including_annotations(&self, node: &SyntaxNode, span: Span) -> Span {
139 children(node)
140 .find(|n| n.kind() == ANNOTATION)
141 .map(|ann| Span::new(self.trimmed_span(&ann).lo, span.hi))
142 .unwrap_or(span)
143 }
144
145 fn to_identifier(&self, token: &SyntaxToken) -> leo_ast::Identifier {
147 debug_assert_eq!(token.kind(), IDENT);
148 leo_ast::Identifier {
149 name: Symbol::intern(token.text()),
150 span: self.token_span(token),
151 id: self.builder.next_id(),
152 }
153 }
154
155 fn error_identifier(&self, span: Span) -> leo_ast::Identifier {
157 leo_ast::Identifier { name: Symbol::intern("_error"), span, id: self.builder.next_id() }
158 }
159
160 fn error_expression(&self, span: Span) -> leo_ast::Expression {
162 leo_ast::ErrExpression { span, id: self.builder.next_id() }.into()
163 }
164
165 fn intrinsic_expression(
167 &self,
168 name: Symbol,
169 arguments: Vec<leo_ast::Expression>,
170 span: Span,
171 ) -> leo_ast::Expression {
172 leo_ast::IntrinsicExpression {
173 name,
174 type_parameters: Vec::new(),
175 input_types: Vec::new(),
176 return_types: Vec::new(),
177 arguments,
178 span,
179 id: self.builder.next_id(),
180 }
181 .into()
182 }
183
184 fn error_block(&self, span: Span) -> leo_ast::Block {
186 leo_ast::Block { statements: Vec::new(), span, id: self.builder.next_id() }
187 }
188
189 fn validate_hexbin_literal(&self, text: &str, suffix_len: u32, span: Span) {
192 if text.starts_with("0x") || text.starts_with("0o") || text.starts_with("0b") {
193 self.handler.emit_err(ParserError::hexbin_literal_nonintegers(Span::new(span.lo, span.hi - suffix_len)));
194 }
195 }
196
197 fn require_ident(&self, node: &SyntaxNode, label: &str) -> leo_ast::Identifier {
199 let span = self.to_span(node);
200 match tokens(node).find(|t| t.kind() == IDENT) {
201 Some(token) => self.to_identifier(&token),
202 None => {
203 self.emit_unexpected_str(label, node.text(), span);
204 self.error_identifier(span)
205 }
206 }
207 }
208
209 fn require_type(&self, node: &SyntaxNode, label: &str) -> Result<leo_ast::Type> {
211 match children(node).find(|n| n.kind().is_type()) {
212 Some(type_node) => self.to_type(&type_node),
213 None => {
214 self.emit_unexpected_str(label, node.text(), self.to_span(node));
215 Ok(leo_ast::Type::Err)
216 }
217 }
218 }
219
220 fn require_expression(&self, node: &SyntaxNode, label: &str) -> Result<leo_ast::Expression> {
222 match children(node).find(|n| n.kind().is_expression()) {
223 Some(expr_node) => self.to_expression(&expr_node),
224 None => {
225 let span = self.to_span(node);
226 self.emit_unexpected_str(label, node.text(), span);
227 Ok(self.error_expression(span))
228 }
229 }
230 }
231
232 fn validate_identifier(&self, ident: &leo_ast::Identifier) {
234 const MAX_IDENTIFIER_LEN: usize = 31;
235 let text = ident.name.to_string();
236 if text.len() > MAX_IDENTIFIER_LEN {
237 self.handler.emit_err(ParserError::identifier_too_long(&text, text.len(), MAX_IDENTIFIER_LEN, ident.span));
238 }
239 if text.contains("__") {
240 self.handler.emit_err(ParserError::identifier_cannot_contain_double_underscore(&text, ident.span));
241 }
242 }
243
244 fn validate_definition_identifier(&self, ident: &leo_ast::Identifier) {
248 if ident.name == Symbol::intern("_error") {
250 return;
251 }
252 self.validate_identifier(ident);
253 let text = ident.name.to_string();
254 if text.starts_with('_') {
255 self.handler.emit_err(ParserError::identifier_cannot_start_with_underscore(ident.span));
256 }
257 if symbol_is_keyword(ident.name) {
258 self.emit_unexpected_str("an identifier", &text, ident.span);
259 }
260 }
261
262 fn to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
268 let ty = match node.kind() {
269 TYPE_PRIMITIVE => self.type_primitive_to_type(node)?,
270 TYPE_LOCATOR => self.type_locator_to_type(node)?,
271 TYPE_PATH => self.type_path_to_type(node)?,
272 TYPE_ARRAY => self.type_array_to_type(node)?,
273 TYPE_VECTOR => self.type_vector_to_type(node)?,
274 TYPE_TUPLE => self.type_tuple_to_type(node)?,
275 TYPE_OPTIONAL => self.type_optional_to_type(node)?,
276 TYPE_FINAL => self.type_final_to_type(node)?,
277 TYPE_MAPPING => self.type_mapping_to_type(node)?,
278 TYPE_DYN_RECORD => leo_ast::Type::DynRecord,
279 ERROR => {
280 leo_ast::Type::Err
282 }
283 kind => panic!("unexpected type node kind: {:?}", kind),
284 };
285 Ok(ty)
286 }
287
288 fn type_primitive_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
290 debug_assert_eq!(node.kind(), TYPE_PRIMITIVE);
291 let prim = tokens(node)
292 .next()
293 .and_then(|t| keyword_to_primitive_type(t.kind()))
294 .expect("TYPE_PRIMITIVE should contain a type keyword");
295 Ok(prim)
296 }
297
298 fn type_locator_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
302 debug_assert_eq!(node.kind(), TYPE_LOCATOR);
303
304 let 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 interfaces: &mut Vec<(Symbol, leo_ast::Interface)>,
1935 ) -> Result<()> {
1936 if is_library_item(item.kind()) {
1937 match item.kind() {
1938 GLOBAL_CONST => {
1939 let global_const = self.to_global_const(item)?;
1940 consts.push((global_const.place.name, global_const));
1941 }
1942 STRUCT_DEF => {
1943 let composite = self.to_composite(item)?;
1944 structs.push((composite.identifier.name, composite));
1945 }
1946 FUNCTION_DEF => {
1947 let func = self.to_function(item, false)?;
1949 functions.push((func.identifier.name, func));
1950 }
1951 INTERFACE_DEF => {
1952 let interface = self.to_interface(item)?;
1953 interfaces.push((interface.identifier.name, interface));
1954 }
1955 _ => {}
1956 }
1957 } else if is_program_item(item.kind()) {
1958 let span = self.to_span(item);
1960 self.handler.emit_err(ParserError::custom(
1961 "Only `const` declarations, `struct` definitions, `fn` functions, and `interface` definitions are allowed in a library.",
1962 span,
1963 ));
1964 }
1965 Ok(())
1968 }
1969
1970 fn to_module(&self, node: &SyntaxNode, program_name: Symbol, path: Vec<Symbol>) -> Result<leo_ast::Module> {
1972 let mut functions = Vec::new();
1974 let mut composites = Vec::new();
1975 let mut consts = Vec::new();
1976 let mut interfaces = Vec::new();
1977
1978 for child in children(node) {
1979 if child.kind() == PROGRAM_DECL {
1980 for item in children(&child) {
1981 self.collect_program_item(
1982 &item,
1983 true,
1984 &mut functions,
1985 &mut composites,
1986 &mut consts,
1987 &mut interfaces,
1988 )?;
1989 }
1990 } else {
1991 self.collect_program_item(
1992 &child,
1993 false,
1994 &mut functions,
1995 &mut composites,
1996 &mut consts,
1997 &mut interfaces,
1998 )?;
1999 }
2000 }
2001
2002 functions.sort_by_key(|func| if func.1.variant.is_entry() { 0u8 } else { 1u8 });
2004
2005 Ok(leo_ast::Module { program_name, path, consts, composites, functions, interfaces })
2006 }
2007
2008 fn to_main(&self, node: &SyntaxNode) -> Result<leo_ast::Program> {
2010 let mut imports = indexmap::IndexMap::new();
2012 let mut functions = Vec::new();
2013 let mut composites = Vec::new();
2014 let mut consts = Vec::new();
2015 let mut mappings = Vec::new();
2016 let mut storage_variables = Vec::new();
2017 let mut constructors = Vec::new();
2018 let mut interfaces = Vec::new();
2019 let mut program_name = None;
2020 let mut network = None;
2021 let mut parents = Vec::new();
2022 let mut span = None;
2023
2024 for child in children(node) {
2025 match child.kind() {
2026 IMPORT => {
2027 let program_id = self.import_to_program_id(&child)?;
2028 imports.insert(program_id.as_symbol(), program_id);
2029 }
2030 PROGRAM_DECL => {
2031 if program_name.is_some() {
2032 self.handler.emit_err(ParserError::multiple_program_declarations(self.non_trivia_span(&child)));
2033 continue;
2034 }
2035 let (pname, pnetwork, pparents) = self.program_decl_to_name_with_parent(&child)?;
2037 program_name = Some(pname);
2038 network = Some(pnetwork);
2039 parents = pparents;
2040 span = Some(self.to_span(&child));
2041
2042 for item in children(&child) {
2044 self.collect_program_item(
2045 &item,
2046 true,
2047 &mut functions,
2048 &mut composites,
2049 &mut consts,
2050 &mut interfaces,
2051 )?;
2052 match item.kind() {
2053 MAPPING_DEF => {
2054 let mapping = self.to_mapping(&item)?;
2055 mappings.push((mapping.identifier.name, mapping));
2056 }
2057 STORAGE_DEF => {
2058 let storage = self.to_storage(&item)?;
2059 storage_variables.push((storage.identifier.name, storage));
2060 }
2061 CONSTRUCTOR_DEF => {
2062 constructors.push(self.to_constructor(&item)?);
2063 }
2064 _ => {}
2065 }
2066 }
2067 }
2068 _ => {
2069 self.collect_program_item(
2070 &child,
2071 false,
2072 &mut functions,
2073 &mut composites,
2074 &mut consts,
2075 &mut interfaces,
2076 )?;
2077 }
2078 }
2079 }
2080
2081 if let Some(extra) = constructors.get(1) {
2082 return Err(ParserError::custom("A program can only have one constructor.", extra.span).into());
2083 }
2084
2085 let (Some(program_name), Some(network), Some(span)) = (program_name, network, span) else {
2086 return Err(ParserError::missing_program_scope(self.to_span(node)).into());
2087 };
2088
2089 functions.sort_by_key(|func| if func.1.variant.is_entry() { 0u8 } else { 1u8 });
2091
2092 let program_id = leo_ast::ProgramId { name: program_name, network };
2093 let program_id_as_symbol = program_id.as_symbol();
2094 let program_scope = leo_ast::ProgramScope {
2095 program_id,
2096 parents,
2097 consts,
2098 composites,
2099 mappings,
2100 storage_variables,
2101 functions,
2102 interfaces,
2103 constructor: constructors.pop(),
2104 span,
2105 };
2106
2107 Ok(leo_ast::Program {
2108 imports,
2109 modules: indexmap::IndexMap::new(),
2110 stubs: indexmap::IndexMap::new(),
2111 program_scopes: vec![(program_id_as_symbol, program_scope)].into_iter().collect(),
2112 })
2113 }
2114
2115 fn to_library(&self, name: Symbol, node: &SyntaxNode) -> Result<leo_ast::Library> {
2117 let mut consts = Vec::new();
2118 let mut structs = Vec::new();
2119 let mut functions = Vec::new();
2120 let mut interfaces = Vec::new();
2121
2122 for child in children(node) {
2123 self.collect_library_item(&child, &mut consts, &mut structs, &mut functions, &mut interfaces)?;
2124 }
2125
2126 Ok(leo_ast::Library { name, modules: indexmap::IndexMap::new(), consts, structs, functions, interfaces })
2127 }
2128
2129 fn import_to_program_id(&self, node: &SyntaxNode) -> Result<leo_ast::ProgramId> {
2131 debug_assert_eq!(node.kind(), IMPORT);
2132 let span = self.to_span(node);
2133
2134 let program_name_text = match tokens(node).find(|t| t.kind() == IDENT) {
2136 Some(name_token) => name_token.text().to_string(),
2137 None => {
2138 self.emit_unexpected_str("import name", node.text(), span);
2139 "_error".to_string()
2140 }
2141 };
2142
2143 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 {
2147 name: leo_ast::Identifier { name: Symbol::intern(&program_name_text), span, id: self.builder.next_id() },
2148 network: leo_ast::Identifier {
2149 name: Symbol::intern("aleo"),
2150 span: network_span,
2151 id: self.builder.next_id(),
2152 },
2153 };
2154
2155 if tokens(node).all(|t| t.kind() != KW_ALEO)
2157 && let Some(net_token) = find_invalid_network(node)
2158 {
2159 self.handler.emit_err(ParserError::invalid_network(self.token_span(&net_token)));
2160 }
2161
2162 Ok(program_id)
2163 }
2164
2165 fn program_decl_to_name(&self, node: &SyntaxNode) -> Result<(leo_ast::Identifier, leo_ast::Identifier)> {
2167 debug_assert_eq!(node.kind(), PROGRAM_DECL);
2168 let span = self.to_span(node);
2169
2170 let program_name = self.require_ident(node, "program name");
2172
2173 let network = match tokens(node).find(|t| t.kind() == KW_ALEO) {
2174 Some(aleo_token) => leo_ast::Identifier {
2175 name: Symbol::intern("aleo"),
2176 span: self.token_span(&aleo_token),
2177 id: self.builder.next_id(),
2178 },
2179 None => {
2180 if let Some(net_token) = find_invalid_network(node) {
2182 self.handler.emit_err(ParserError::invalid_network(self.token_span(&net_token)));
2183 } else {
2184 self.emit_unexpected_str(".aleo network", node.text(), span);
2185 }
2186 leo_ast::Identifier { name: Symbol::intern("aleo"), span, id: self.builder.next_id() }
2187 }
2188 };
2189
2190 Ok((program_name, network))
2191 }
2192
2193 fn program_decl_to_name_with_parent(
2195 &self,
2196 node: &SyntaxNode,
2197 ) -> Result<(leo_ast::Identifier, leo_ast::Identifier, Parents)> {
2198 debug_assert_eq!(node.kind(), PROGRAM_DECL);
2199 let (program_name, network) = self.program_decl_to_name(node)?;
2200
2201 let parents = if let Some(parent_list) = children(node).find(|n| n.kind() == PARENT_LIST) {
2202 self.collect_parent_list(&parent_list)?
2203 } else {
2204 vec![]
2205 };
2206
2207 Ok((program_name, network, parents))
2208 }
2209
2210 fn collect_parent_list(&self, node: &SyntaxNode) -> Result<Parents> {
2211 debug_assert_eq!(node.kind(), PARENT_LIST);
2212 children(node)
2213 .filter(|n| n.kind().is_type())
2214 .map(|n| self.to_type(&n).map(|t| (self.to_span(&n), t)))
2215 .collect::<Result<Vec<_>>>()
2216 }
2217
2218 fn collect_annotations(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::Annotation>> {
2220 children(node).filter(|n| n.kind() == ANNOTATION).map(|n| self.to_annotation(&n)).collect()
2221 }
2222
2223 fn require_block(&self, node: &SyntaxNode, span: Span) -> Result<leo_ast::Block> {
2225 Ok(children(node)
2226 .find(|n| n.kind() == BLOCK)
2227 .map(|n| self.to_block(&n))
2228 .transpose()?
2229 .unwrap_or_else(|| self.error_block(span)))
2230 }
2231
2232 fn to_function(&self, node: &SyntaxNode, is_in_program_block: bool) -> Result<leo_ast::Function> {
2234 debug_assert!(matches!(node.kind(), FUNCTION_DEF | FINAL_FN_DEF | CONSTRUCTOR_DEF));
2235 let span = self.span_including_annotations(node, self.non_trivia_span(node));
2236 let id = self.builder.next_id();
2237
2238 let annotations = self.collect_annotations(node)?;
2239
2240 let variant = if is_in_program_block {
2242 leo_ast::Variant::EntryPoint
2243 } else {
2244 match node.kind() {
2245 FINAL_FN_DEF => leo_ast::Variant::FinalFn,
2246 _ => leo_ast::Variant::Fn,
2247 }
2248 };
2249
2250 let identifier = self.require_ident(node, "function name");
2251 self.validate_identifier(&identifier);
2252
2253 let const_parameters = self.extract_const_parameters(node)?;
2254
2255 let input = children(node)
2257 .find(|n| n.kind() == PARAM_LIST)
2258 .map(|n| self.param_list_to_inputs(&n))
2259 .transpose()?
2260 .unwrap_or_default();
2261
2262 let (output, output_type) = if let Some(return_type_node) = children(node).find(|n| n.kind() == RETURN_TYPE) {
2268 self.return_type_to_outputs(&return_type_node)?
2270 } else if let Some(type_node) = children(node).find(|n| n.kind().is_type()) {
2271 let type_ = self.to_type(&type_node)?;
2273 let (mode, mode_start) = self.return_mode_before(node, &type_node);
2275 let type_span = self.content_span(&type_node);
2276 let output_span = match mode_start {
2277 Some(start) => Span::new(start, type_span.hi),
2278 None => type_span,
2279 };
2280 let output =
2281 vec![leo_ast::Output { mode, type_: type_.clone(), span: output_span, id: self.builder.next_id() }];
2282 (output, type_)
2283 } else {
2284 (Vec::new(), leo_ast::Type::Unit)
2285 };
2286
2287 let block = self.require_block(node, span)?;
2288
2289 Ok(leo_ast::Function {
2290 annotations,
2291 variant,
2292 identifier,
2293 const_parameters,
2294 input,
2295 output,
2296 output_type,
2297 block,
2298 span,
2299 id,
2300 })
2301 }
2302
2303 fn return_mode_before(&self, parent: &SyntaxNode, type_node: &SyntaxNode) -> (leo_ast::Mode, Option<u32>) {
2309 let type_start = type_node.text_range().start();
2310 let mut mode = leo_ast::Mode::None;
2311 let mut mode_start = None;
2312 for token in tokens(parent) {
2313 let token_end = token.text_range().end();
2314 if token_end > type_start {
2315 break;
2316 }
2317 if let Some(m) = token_kind_to_mode(token.kind()) {
2318 mode = m;
2319 mode_start = Some(u32::from(token.text_range().start()) + self.start_pos);
2320 }
2321 }
2322 (mode, mode_start)
2323 }
2324
2325 fn return_type_to_outputs(&self, node: &SyntaxNode) -> Result<(Vec<leo_ast::Output>, leo_ast::Type)> {
2327 debug_assert_eq!(node.kind(), RETURN_TYPE);
2328
2329 let mut outputs = Vec::new();
2332 let mut current_mode = leo_ast::Mode::None;
2333 let mut current_mode_start: Option<u32> = None;
2334
2335 for child in node.children_with_tokens() {
2336 match &child {
2337 SyntaxElement::Token(token) if !token.kind().is_trivia() => {
2338 if let Some(m) = token_kind_to_mode(token.kind()) {
2339 current_mode = m;
2340 current_mode_start = Some(u32::from(token.text_range().start()) + self.start_pos);
2341 }
2342 }
2343 SyntaxElement::Node(child_node) if child_node.kind().is_type() => {
2344 let type_ = self.to_type(child_node)?;
2345 let type_span = self.content_span(child_node);
2346 let output_span = match current_mode_start.take() {
2347 Some(start) => Span::new(start, type_span.hi),
2348 None => type_span,
2349 };
2350 outputs.push(leo_ast::Output {
2351 mode: current_mode,
2352 type_,
2353 span: output_span,
2354 id: self.builder.next_id(),
2355 });
2356 current_mode = leo_ast::Mode::None;
2357 }
2358 _ => {}
2359 }
2360 }
2361
2362 let output_type = match outputs.len() {
2363 0 => leo_ast::Type::Unit,
2364 1 => outputs[0].type_.clone(),
2365 _ => leo_ast::TupleType::new(outputs.iter().map(|o| o.type_.clone()).collect()).into(),
2366 };
2367
2368 Ok((outputs, output_type))
2369 }
2370
2371 fn to_annotation(&self, node: &SyntaxNode) -> Result<leo_ast::Annotation> {
2373 debug_assert_eq!(node.kind(), ANNOTATION);
2374 let span = self.trimmed_span(node);
2375 let id = self.builder.next_id();
2376
2377 let name_token =
2380 tokens(node).find(|t| t.kind() == IDENT || t.kind().is_keyword()).expect("annotation should have name");
2381 let name = Symbol::intern(name_token.text());
2382 let name_span = self.token_span(&name_token);
2383 let identifier = leo_ast::Identifier { name, span: name_span, id: self.builder.next_id() };
2384
2385 let map = children(node)
2387 .filter(|n| n.kind() == ANNOTATION_PAIR)
2388 .filter_map(|pair| {
2389 let key =
2390 tokens(&pair).find(|t| t.kind() == IDENT || t.kind() == KW_ADDRESS || t.kind() == KW_MAPPING)?;
2391 let val = tokens(&pair).find(|t| t.kind() == STRING)?;
2392 let text = val.text();
2393 Some((Symbol::intern(key.text()), text[1..text.len() - 1].to_string()))
2394 })
2395 .collect();
2396
2397 Ok(leo_ast::Annotation { identifier, map, span, id })
2398 }
2399
2400 fn param_list_to_inputs(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::Input>> {
2402 debug_assert_eq!(node.kind(), PARAM_LIST);
2403
2404 children(node)
2405 .filter(|n| matches!(n.kind(), PARAM | PARAM_PUBLIC | PARAM_PRIVATE | PARAM_CONSTANT))
2406 .map(|n| self.param_to_input(&n))
2407 .collect()
2408 }
2409
2410 fn param_to_input(&self, node: &SyntaxNode) -> Result<leo_ast::Input> {
2412 debug_assert!(matches!(node.kind(), PARAM | PARAM_PUBLIC | PARAM_PRIVATE | PARAM_CONSTANT));
2413 let span = self.non_trivia_span(node);
2414 let id = self.builder.next_id();
2415
2416 let mode = node_kind_to_mode(node.kind());
2417
2418 let identifier = self.require_ident(node, "parameter name");
2419 self.validate_identifier(&identifier);
2420
2421 let type_ = self.require_type(node, "parameter type")?;
2422
2423 Ok(leo_ast::Input { identifier, mode, type_, span, id })
2424 }
2425
2426 fn to_const_parameters(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::ConstParameter>> {
2428 debug_assert_eq!(node.kind(), CONST_PARAM_LIST);
2429
2430 children(node)
2431 .filter(|n| n.kind() == CONST_PARAM)
2432 .map(|n| {
2433 let span = self.non_trivia_span(&n);
2434 let id = self.builder.next_id();
2435
2436 let identifier = self.require_ident(&n, "const parameter name");
2437
2438 let type_ = self.require_type(&n, "const parameter type")?;
2439
2440 Ok(leo_ast::ConstParameter { identifier, type_, span, id })
2441 })
2442 .collect()
2443 }
2444
2445 fn extract_const_parameters(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::ConstParameter>> {
2447 children(node)
2448 .find(|n| n.kind() == CONST_PARAM_LIST)
2449 .map(|n| self.to_const_parameters(&n))
2450 .transpose()
2451 .map(|opt| opt.unwrap_or_default())
2452 }
2453
2454 fn to_composite(&self, node: &SyntaxNode) -> Result<leo_ast::Composite> {
2456 debug_assert!(matches!(node.kind(), STRUCT_DEF | RECORD_DEF));
2457 let span = self.non_trivia_span(node);
2458 let id = self.builder.next_id();
2459
2460 let is_record = node.kind() == RECORD_DEF;
2461
2462 let identifier = self.require_ident(node, "struct/record name");
2463 self.validate_identifier(&identifier);
2464
2465 let const_parameters = self.extract_const_parameters(node)?;
2466
2467 let members = children(node)
2469 .filter(|n| {
2470 matches!(
2471 n.kind(),
2472 STRUCT_MEMBER | STRUCT_MEMBER_PUBLIC | STRUCT_MEMBER_PRIVATE | STRUCT_MEMBER_CONSTANT
2473 )
2474 })
2475 .map(|n| self.struct_member_to_member(&n))
2476 .collect::<Result<Vec<_>>>()?;
2477
2478 Ok(leo_ast::Composite { identifier, const_parameters, members, is_record, span, id })
2479 }
2480
2481 fn struct_member_to_member(&self, node: &SyntaxNode) -> Result<leo_ast::Member> {
2483 debug_assert!(matches!(
2484 node.kind(),
2485 STRUCT_MEMBER | STRUCT_MEMBER_PUBLIC | STRUCT_MEMBER_PRIVATE | STRUCT_MEMBER_CONSTANT
2486 ));
2487 let span = self.non_trivia_span(node);
2488 let id = self.builder.next_id();
2489
2490 let mode = node_kind_to_mode(node.kind());
2491
2492 let identifier = self.require_ident(node, "member name");
2493 self.validate_identifier(&identifier);
2494
2495 let type_ = self.require_type(node, "member type")?;
2496
2497 Ok(leo_ast::Member { mode, identifier, type_, span, id })
2498 }
2499
2500 fn to_global_const(&self, node: &SyntaxNode) -> Result<leo_ast::ConstDeclaration> {
2502 debug_assert_eq!(node.kind(), GLOBAL_CONST);
2503 let span = self.non_trivia_span(node);
2504 let id = self.builder.next_id();
2505
2506 let place = self.require_ident(node, "const name");
2507 self.validate_definition_identifier(&place);
2508
2509 let type_ = self.require_type(node, "const type")?;
2510
2511 let value = self.require_expression(node, "const value")?;
2512
2513 Ok(leo_ast::ConstDeclaration { place, type_, value, span, id })
2514 }
2515
2516 fn parse_mapping_def(
2518 &self,
2519 node: &SyntaxNode,
2520 ) -> Result<(leo_ast::Identifier, leo_ast::Type, leo_ast::Type, Span, NodeID)> {
2521 debug_assert_eq!(node.kind(), MAPPING_DEF);
2522 let span = self.non_trivia_span(node);
2523 let id = self.builder.next_id();
2524 let identifier = self.require_ident(node, "name in mapping");
2525 let mut type_nodes = children(node).filter(|n| n.kind().is_type());
2526 let key_type = match type_nodes.next() {
2527 Some(key_node) => self.to_type(&key_node)?,
2528 None => {
2529 self.emit_unexpected_str("key type in mapping", node.text(), span);
2530 leo_ast::Type::Err
2531 }
2532 };
2533 let value_type = match type_nodes.next() {
2534 Some(value_node) => self.to_type(&value_node)?,
2535 None => {
2536 self.emit_unexpected_str("value type in mapping", node.text(), span);
2537 leo_ast::Type::Err
2538 }
2539 };
2540 Ok((identifier, key_type, value_type, span, id))
2541 }
2542
2543 fn to_mapping(&self, node: &SyntaxNode) -> Result<leo_ast::Mapping> {
2545 let (identifier, key_type, value_type, span, id) = self.parse_mapping_def(node)?;
2546 Ok(leo_ast::Mapping { identifier, key_type, value_type, span, id })
2547 }
2548
2549 fn to_mapping_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::MappingPrototype> {
2551 let (identifier, key_type, value_type, span, id) = self.parse_mapping_def(node)?;
2552 Ok(leo_ast::MappingPrototype { identifier, key_type, value_type, span, id })
2553 }
2554
2555 fn parse_storage_def(&self, node: &SyntaxNode) -> Result<(leo_ast::Identifier, leo_ast::Type, Span, NodeID)> {
2557 debug_assert_eq!(node.kind(), STORAGE_DEF);
2558 let span = self.non_trivia_span(node);
2559 let id = self.builder.next_id();
2560 let identifier = self.require_ident(node, "name in storage");
2561 let type_ = self.require_type(node, "type in storage")?;
2562 Ok((identifier, type_, span, id))
2563 }
2564
2565 fn to_storage(&self, node: &SyntaxNode) -> Result<leo_ast::StorageVariable> {
2567 let (identifier, type_, span, id) = self.parse_storage_def(node)?;
2568 Ok(leo_ast::StorageVariable { identifier, type_, span, id })
2569 }
2570
2571 fn to_storage_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::StorageVariablePrototype> {
2573 let (identifier, type_, span, id) = self.parse_storage_def(node)?;
2574 Ok(leo_ast::StorageVariablePrototype { identifier, type_, span, id })
2575 }
2576
2577 fn to_constructor(&self, node: &SyntaxNode) -> Result<leo_ast::Constructor> {
2579 debug_assert_eq!(node.kind(), CONSTRUCTOR_DEF);
2580 let span = self.span_including_annotations(node, self.non_trivia_span(node));
2581 let id = self.builder.next_id();
2582
2583 let annotations = self.collect_annotations(node)?;
2584 let block = self.require_block(node, span)?;
2585
2586 Ok(leo_ast::Constructor { annotations, block, span, id })
2587 }
2588
2589 fn to_interface(&self, node: &SyntaxNode) -> Result<leo_ast::Interface> {
2595 debug_assert_eq!(node.kind(), INTERFACE_DEF);
2596 let span = self.to_span(node);
2597
2598 let identifier = self.require_ident(node, "interface name");
2600
2601 let parents = if let Some(parent_list) = children(node).find(|n| n.kind() == PARENT_LIST) {
2604 self.collect_parent_list(&parent_list)?
2605 } else {
2606 vec![]
2607 };
2608
2609 let mut functions = Vec::new();
2610 let mut records = Vec::new();
2611 let mut mappings = Vec::new();
2612 let mut storages = Vec::new();
2613
2614 for child in children(node) {
2615 match child.kind() {
2616 FN_PROTOTYPE_DEF => {
2617 let proto = self.to_function_prototype(&child)?;
2618 functions.push((proto.identifier.name, proto));
2619 }
2620 RECORD_PROTOTYPE_DEF => {
2621 let proto = self.to_record_prototype(&child)?;
2622 records.push((proto.identifier.name, proto));
2623 }
2624 MAPPING_DEF => {
2625 let mapping = self.to_mapping_prototype(&child)?;
2626 mappings.push(mapping);
2627 }
2628 STORAGE_DEF => {
2629 let storage = self.to_storage_prototype(&child)?;
2630 storages.push(storage);
2631 }
2632 _ => {}
2633 }
2634 }
2635
2636 Ok(leo_ast::Interface {
2637 identifier,
2638 parents,
2639 span,
2640 id: self.builder.next_id(),
2641 functions,
2642 records,
2643 mappings,
2644 storages,
2645 })
2646 }
2647
2648 fn to_function_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::FunctionPrototype> {
2650 debug_assert_eq!(node.kind(), FN_PROTOTYPE_DEF);
2651 let span = self.to_span(node);
2652
2653 let identifier = self.require_ident(node, "function name");
2654
2655 let const_parameters = self.extract_const_parameters(node)?;
2657
2658 let input = children(node)
2660 .find(|n| n.kind() == PARAM_LIST)
2661 .map(|n| self.param_list_to_inputs(&n))
2662 .transpose()?
2663 .unwrap_or_default();
2664
2665 let output = if let Some(return_type_node) = children(node).find(|n| n.kind() == RETURN_TYPE) {
2668 self.return_type_to_outputs(&return_type_node)?.0
2670 } else if let Some(type_node) = children(node).find(|n| n.kind().is_type()) {
2671 let type_ = self.to_type(&type_node)?;
2673 let (mode, mode_start) = self.return_mode_before(node, &type_node);
2675 let type_span = self.content_span(&type_node);
2676 let output_span = match mode_start {
2677 Some(start) => Span::new(start, type_span.hi),
2678 None => type_span,
2679 };
2680 vec![leo_ast::Output { mode, type_, span: output_span, id: self.builder.next_id() }]
2681 } else {
2682 Vec::new()
2683 };
2684
2685 Ok(leo_ast::FunctionPrototype::new(
2686 vec![], identifier,
2688 const_parameters,
2689 input,
2690 output,
2691 span,
2692 self.builder.next_id(),
2693 ))
2694 }
2695
2696 fn to_record_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::RecordPrototype> {
2698 debug_assert_eq!(node.kind(), RECORD_PROTOTYPE_DEF);
2699
2700 let span = self.to_span(node);
2701 let identifier = self.require_ident(node, "record name");
2702 let members = children(node)
2703 .filter(|n| {
2704 matches!(
2705 n.kind(),
2706 STRUCT_MEMBER | STRUCT_MEMBER_PUBLIC | STRUCT_MEMBER_PRIVATE | STRUCT_MEMBER_CONSTANT
2707 )
2708 })
2709 .map(|n| self.struct_member_to_member(&n))
2710 .collect::<Result<Vec<_>>>()?;
2711
2712 let is_redundant = members.is_empty()
2714 || members.iter().all(|m| {
2715 m.identifier.name == sym::owner && m.type_ == leo_ast::Type::Address && m.mode == leo_ast::Mode::None
2716 });
2717 if is_redundant && !members.is_empty() {
2718 self.handler.emit_warning(ParserWarning::record_prototype_redundant(identifier.name, span));
2720 return Ok(leo_ast::RecordPrototype { identifier, span, members: Vec::new(), id: self.builder.next_id() });
2721 } else if is_redundant {
2722 let had_braces = node.children_with_tokens().any(|c| c.kind() == L_BRACE);
2725 if had_braces {
2726 self.handler.emit_warning(ParserWarning::record_prototype_redundant(identifier.name, span));
2727 }
2728 }
2729
2730 Ok(leo_ast::RecordPrototype { identifier, span, members, id: self.builder.next_id() })
2731 }
2732}
2733
2734fn clamped_span(range: TextRange, start_pos: u32, source_len: u32) -> Span {
2740 let end = start_pos + source_len;
2741 let lo = (u32::from(range.start()) + start_pos).min(end);
2742 let hi = (u32::from(range.end()) + start_pos).min(end).max(lo);
2743 Span::new(lo, hi)
2744}
2745
2746fn emit_lex_errors(handler: &Handler, lex_errors: &[leo_parser_rowan::LexError], start_pos: u32, source_len: u32) {
2748 use leo_parser_rowan::LexErrorKind;
2749 for error in lex_errors {
2750 let span = clamped_span(error.range, start_pos, source_len);
2751
2752 match &error.kind {
2753 LexErrorKind::InvalidDigit { digit, radix, token } => {
2754 handler.emit_err(ParserError::wrong_digit_for_radix_span(*digit, *radix, token, span));
2755 }
2756 LexErrorKind::CouldNotLex { content } => {
2757 handler.emit_err(ParserError::could_not_lex_span(content, span));
2758 }
2759 LexErrorKind::BidiOverride => {
2760 handler.emit_err(ParserError::lexer_bidi_override_span(span));
2761 }
2762 }
2763 }
2764}
2765
2766fn emit_parse_errors(
2769 handler: &Handler,
2770 errors: &[leo_parser_rowan::ParseError],
2771 start_pos: u32,
2772 source_len: u32,
2773 lex_errors: &[leo_parser_rowan::LexError],
2774) {
2775 use std::collections::HashSet;
2776
2777 let has_lex_errors = !lex_errors.is_empty();
2778
2779 let lex_ranges: Vec<(u32, u32)> = lex_errors
2781 .iter()
2782 .map(|e| {
2783 let lo = u32::from(e.range.start()).saturating_add(start_pos);
2784 let hi = u32::from(e.range.end()).saturating_add(start_pos);
2785 (lo, hi)
2786 })
2787 .collect();
2788
2789 let mut emitted_ranges: HashSet<(u32, u32)> = HashSet::new();
2791 let mut count = 0;
2792 let max_errors = 10;
2793
2794 for error in errors {
2795 if count >= max_errors {
2796 break;
2797 }
2798
2799 let span = clamped_span(error.range, start_pos, source_len);
2800 let range_key = (span.lo, span.hi);
2801
2802 if emitted_ranges.contains(&range_key) {
2804 continue;
2805 }
2806
2807 if has_lex_errors && span.lo == span.hi && span.hi == start_pos + source_len {
2810 continue;
2811 }
2812
2813 if lex_ranges.iter().any(|&(lo, hi)| span.lo < hi && span.hi > lo) {
2816 continue;
2817 }
2818
2819 emitted_ranges.insert(range_key);
2820
2821 let is_eof_error = match &error.found {
2824 Some(f) => f.is_empty() || f == "end of file",
2825 None => false,
2826 } || (span.lo == span.hi && span.hi >= start_pos + source_len);
2827
2828 if is_eof_error {
2829 handler.emit_err(ParserError::unexpected_eof(span));
2830 count += 1;
2831 continue;
2832 }
2833
2834 if let Some(found) = &error.found {
2836 if error.expected.is_empty() {
2837 handler.emit_err(ParserError::custom(&error.message, span));
2840 } else {
2841 let expected_str = error.expected.join(", ");
2842 handler.emit_err(ParserError::unexpected(found, expected_str, span));
2843 }
2844 count += 1;
2845 continue;
2846 }
2847
2848 handler.emit_err(ParserError::custom(&error.message, span));
2850 count += 1;
2851 }
2852}
2853
2854fn conversion_context<'a>(
2856 handler: &'a Handler,
2857 node_builder: &'a NodeBuilder,
2858 lex_errors: &[leo_parser_rowan::LexError],
2859 parse_errors: &[leo_parser_rowan::ParseError],
2860 start_pos: u32,
2861 source_len: u32,
2862) -> ConversionContext<'a> {
2863 emit_lex_errors(handler, lex_errors, start_pos, source_len);
2864 emit_parse_errors(handler, parse_errors, start_pos, source_len, lex_errors);
2865 let has_errors = !parse_errors.is_empty() || !lex_errors.is_empty();
2866 ConversionContext::new(handler, node_builder, start_pos, has_errors)
2867}
2868
2869pub fn parse_expression(
2871 handler: Handler,
2872 node_builder: &NodeBuilder,
2873 source: &str,
2874 start_pos: u32,
2875 _network: NetworkName,
2876) -> Result<leo_ast::Expression> {
2877 let parse = leo_parser_rowan::parse_expression_entry(source);
2878 let ctx =
2879 conversion_context(&handler, node_builder, parse.lex_errors(), parse.errors(), start_pos, source.len() as u32);
2880 ctx.to_expression(&parse.syntax())
2881}
2882
2883pub fn parse_statement(
2885 handler: Handler,
2886 node_builder: &NodeBuilder,
2887 source: &str,
2888 start_pos: u32,
2889 _network: NetworkName,
2890) -> Result<leo_ast::Statement> {
2891 let parse = leo_parser_rowan::parse_statement_entry(source);
2892 let ctx =
2893 conversion_context(&handler, node_builder, parse.lex_errors(), parse.errors(), start_pos, source.len() as u32);
2894 ctx.to_statement(&parse.syntax())
2895}
2896
2897pub fn parse_module(
2899 handler: Handler,
2900 node_builder: &NodeBuilder,
2901 source: &str,
2902 start_pos: u32,
2903 program_name: Symbol,
2904 path: Vec<Symbol>,
2905 _network: NetworkName,
2906) -> Result<leo_ast::Module> {
2907 let parse = leo_parser_rowan::parse_module_entry(source);
2908 let ctx =
2909 conversion_context(&handler, node_builder, parse.lex_errors(), parse.errors(), start_pos, source.len() as u32);
2910 ctx.to_module(&parse.syntax(), program_name, path)
2911}
2912
2913pub fn parse_program(
2915 handler: Handler,
2916 node_builder: &NodeBuilder,
2917 source: &SourceFile,
2918 modules: &[std::rc::Rc<SourceFile>],
2919 _network: NetworkName,
2920) -> Result<leo_ast::Program> {
2921 let parse = leo_parser_rowan::parse_file(&source.src);
2923 let main_context = conversion_context(
2924 &handler,
2925 node_builder,
2926 parse.lex_errors(),
2927 parse.errors(),
2928 source.absolute_start,
2929 source.src.len() as u32,
2930 );
2931 let mut program = main_context.to_main(&parse.syntax())?;
2932 let program_name = *program.program_scopes.first().unwrap().0;
2933
2934 let root_dir = match &source.name {
2936 FileName::Real(path) => path.parent().map(|p| p.to_path_buf()),
2937 _ => None,
2938 };
2939
2940 for module in modules {
2941 let module_parse = leo_parser_rowan::parse_module_entry(&module.src);
2942 let module_context = conversion_context(
2943 &handler,
2944 node_builder,
2945 module_parse.lex_errors(),
2946 module_parse.errors(),
2947 module.absolute_start,
2948 module.src.len() as u32,
2949 );
2950
2951 if let Some(key) = compute_module_key(&module.name, root_dir.as_deref()) {
2952 for segment in &key {
2953 if symbol_is_keyword(*segment) {
2954 return Err(ParserError::keyword_used_as_module_name(key.iter().format("::"), segment).into());
2955 }
2956 }
2957 let module_ast = module_context.to_module(&module_parse.syntax(), program_name, key.clone())?;
2958 program.modules.insert(key, module_ast);
2959 }
2960 }
2961
2962 Ok(program)
2963}
2964
2965pub fn parse_library(
2967 handler: Handler,
2968 node_builder: &NodeBuilder,
2969 library_name: Symbol,
2970 source: &SourceFile,
2971 modules: &[std::rc::Rc<SourceFile>],
2972 _network: NetworkName,
2973) -> Result<leo_ast::Library> {
2974 let parse = leo_parser_rowan::parse_file(&source.src);
2976 let main_context = conversion_context(
2977 &handler,
2978 node_builder,
2979 parse.lex_errors(),
2980 parse.errors(),
2981 source.absolute_start,
2982 source.src.len() as u32,
2983 );
2984
2985 let mut library = main_context.to_library(library_name, &parse.syntax())?;
2986
2987 let root_dir = match &source.name {
2989 FileName::Real(path) => path.parent().map(|p| p.to_path_buf()),
2990 _ => None,
2991 };
2992
2993 for module_sf in modules {
2995 let module_parse = leo_parser_rowan::parse_module_entry(&module_sf.src);
2996 let module_context = conversion_context(
2997 &handler,
2998 node_builder,
2999 module_parse.lex_errors(),
3000 module_parse.errors(),
3001 module_sf.absolute_start,
3002 module_sf.src.len() as u32,
3003 );
3004
3005 if let Some(key) = compute_module_key(&module_sf.name, root_dir.as_deref()) {
3006 for segment in &key {
3007 if symbol_is_keyword(*segment) {
3008 return Err(ParserError::keyword_used_as_module_name(key.iter().format("::"), segment).into());
3009 }
3010 }
3011 let module_ast = module_context.to_module(&module_parse.syntax(), library_name, key.clone())?;
3014 library.modules.insert(key, module_ast);
3015 }
3016 }
3017
3018 Ok(library)
3019}
3020
3021fn children(node: &SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ {
3027 node.children().filter(|n| !n.kind().is_trivia())
3028}
3029
3030fn tokens(node: &SyntaxNode) -> impl Iterator<Item = SyntaxToken> + '_ {
3032 node.children_with_tokens().filter_map(|elem| elem.into_token()).filter(|t| !t.kind().is_trivia())
3033}
3034
3035fn find_name_after_dot(node: &SyntaxNode) -> Option<SyntaxToken> {
3037 let dot_end = tokens(node).find(|t| t.kind() == DOT)?.text_range().end();
3038 tokens(node).filter(|t| t.text_range().start() >= dot_end).find(|t| t.kind() == IDENT || t.kind().is_keyword())
3039}
3040
3041fn first_non_trivia_token(node: &SyntaxNode) -> Option<SyntaxToken> {
3043 node.children_with_tokens().find_map(|e| e.into_token().filter(|t| !t.kind().is_trivia()))
3044}
3045
3046fn last_non_trivia_token(node: &SyntaxNode) -> Option<SyntaxToken> {
3048 node.children_with_tokens().filter_map(|e| e.into_token().filter(|t| !t.kind().is_trivia())).last()
3049}
3050
3051fn find_invalid_network(node: &SyntaxNode) -> Option<SyntaxToken> {
3053 let mut saw_dot = false;
3054 tokens(node).find(|t| {
3055 if t.kind() == DOT {
3056 saw_dot = true;
3057 return false;
3058 }
3059 saw_dot && t.kind() == IDENT
3060 })
3061}
3062
3063fn token_kind_to_mode(kind: SyntaxKind) -> Option<leo_ast::Mode> {
3065 match kind {
3066 KW_PUBLIC => Some(leo_ast::Mode::Public),
3067 KW_PRIVATE => Some(leo_ast::Mode::Private),
3068 KW_CONSTANT => Some(leo_ast::Mode::Constant),
3069 _ => None,
3070 }
3071}
3072
3073fn node_kind_to_mode(kind: SyntaxKind) -> leo_ast::Mode {
3075 match kind {
3076 PARAM_PUBLIC | STRUCT_MEMBER_PUBLIC => leo_ast::Mode::Public,
3077 PARAM_PRIVATE | STRUCT_MEMBER_PRIVATE => leo_ast::Mode::Private,
3078 PARAM_CONSTANT | STRUCT_MEMBER_CONSTANT => leo_ast::Mode::Constant,
3079 _ => leo_ast::Mode::None,
3080 }
3081}
3082
3083fn keyword_to_path_symbol(kind: SyntaxKind) -> Option<Symbol> {
3085 match kind {
3086 KW_SELF => Some(sym::SelfLower),
3087 KW_BLOCK => Some(sym::block),
3088 KW_NETWORK => Some(sym::network),
3089 KW_FINAL_UPPER => Some(sym::Final),
3090 _ => None,
3091 }
3092}
3093
3094fn is_assign_op(kind: SyntaxKind) -> bool {
3096 matches!(
3097 kind,
3098 EQ | PLUS_EQ
3099 | MINUS_EQ
3100 | STAR_EQ
3101 | SLASH_EQ
3102 | PERCENT_EQ
3103 | STAR2_EQ
3104 | AMP_EQ
3105 | PIPE_EQ
3106 | CARET_EQ
3107 | SHL_EQ
3108 | SHR_EQ
3109 | AMP2_EQ
3110 | PIPE2_EQ
3111 )
3112}
3113
3114fn keyword_to_primitive_type(kind: SyntaxKind) -> Option<leo_ast::Type> {
3116 let ty = match kind {
3117 KW_ADDRESS => leo_ast::Type::Address,
3118 KW_BOOL => leo_ast::Type::Boolean,
3119 KW_FIELD => leo_ast::Type::Field,
3120 KW_GROUP => leo_ast::Type::Group,
3121 KW_SCALAR => leo_ast::Type::Scalar,
3122 KW_SIGNATURE => leo_ast::Type::Signature,
3123 KW_STRING => leo_ast::Type::String,
3124 KW_DYN => leo_ast::Type::DynRecord,
3125 KW_IDENTIFIER => leo_ast::Type::Identifier,
3126 KW_U8 => leo_ast::Type::Integer(leo_ast::IntegerType::U8),
3127 KW_U16 => leo_ast::Type::Integer(leo_ast::IntegerType::U16),
3128 KW_U32 => leo_ast::Type::Integer(leo_ast::IntegerType::U32),
3129 KW_U64 => leo_ast::Type::Integer(leo_ast::IntegerType::U64),
3130 KW_U128 => leo_ast::Type::Integer(leo_ast::IntegerType::U128),
3131 KW_I8 => leo_ast::Type::Integer(leo_ast::IntegerType::I8),
3132 KW_I16 => leo_ast::Type::Integer(leo_ast::IntegerType::I16),
3133 KW_I32 => leo_ast::Type::Integer(leo_ast::IntegerType::I32),
3134 KW_I64 => leo_ast::Type::Integer(leo_ast::IntegerType::I64),
3135 KW_I128 => leo_ast::Type::Integer(leo_ast::IntegerType::I128),
3136 _ => return None,
3137 };
3138 Some(ty)
3139}
3140
3141fn token_to_binary_op(kind: SyntaxKind) -> leo_ast::BinaryOperation {
3143 match kind {
3144 EQ2 => leo_ast::BinaryOperation::Eq,
3145 BANG_EQ => leo_ast::BinaryOperation::Neq,
3146 LT => leo_ast::BinaryOperation::Lt,
3147 LT_EQ => leo_ast::BinaryOperation::Lte,
3148 GT => leo_ast::BinaryOperation::Gt,
3149 GT_EQ => leo_ast::BinaryOperation::Gte,
3150 PLUS => leo_ast::BinaryOperation::Add,
3151 MINUS => leo_ast::BinaryOperation::Sub,
3152 STAR => leo_ast::BinaryOperation::Mul,
3153 SLASH => leo_ast::BinaryOperation::Div,
3154 PERCENT => leo_ast::BinaryOperation::Rem,
3155 PIPE2 => leo_ast::BinaryOperation::Or,
3156 AMP2 => leo_ast::BinaryOperation::And,
3157 PIPE => leo_ast::BinaryOperation::BitwiseOr,
3158 AMP => leo_ast::BinaryOperation::BitwiseAnd,
3159 STAR2 => leo_ast::BinaryOperation::Pow,
3160 SHL => leo_ast::BinaryOperation::Shl,
3161 SHR => leo_ast::BinaryOperation::Shr,
3162 CARET => leo_ast::BinaryOperation::Xor,
3163 _ => panic!("unexpected binary operator: {:?}", kind),
3164 }
3165}
3166
3167fn symbol_is_keyword(symbol: Symbol) -> bool {
3168 matches!(
3169 symbol,
3170 sym::address
3171 | sym::aleo
3172 | sym::As
3173 | sym::assert
3174 | sym::assert_eq
3175 | sym::assert_neq
3176 | sym::block
3177 | sym::bool
3178 | sym::Const
3179 | sym::constant
3180 | sym::constructor
3181 | sym::Else
3182 | sym::False
3183 | sym::field
3184 | sym::FnUpper
3185 | sym::Fn
3186 | sym::For
3187 | sym::Final
3188 | sym::group
3189 | sym::i8
3190 | sym::i16
3191 | sym::i32
3192 | sym::i64
3193 | sym::i128
3194 | sym::If
3195 | sym::import
3196 | sym::In
3197 | sym::inline
3198 | sym::Let
3199 | sym::leo
3200 | sym::mapping
3201 | sym::storage
3202 | sym::network
3203 | sym::private
3204 | sym::program
3205 | sym::public
3206 | sym::record
3207 | sym::Return
3208 | sym::scalar
3209 | sym::script
3210 | sym::SelfLower
3211 | sym::signature
3212 | sym::string
3213 | sym::Struct
3214 | sym::True
3215 | sym::u8
3216 | sym::u16
3217 | sym::u32
3218 | sym::u64
3219 | sym::u128
3220 )
3221}
3222
3223fn compute_module_key(name: &FileName, root_dir: Option<&std::path::Path>) -> Option<Vec<Symbol>> {
3225 let path = match name {
3226 FileName::Custom(name) => std::path::Path::new(name).to_path_buf(),
3227 FileName::Real(path) => {
3228 let root = root_dir?;
3229 path.strip_prefix(root).ok()?.to_path_buf()
3230 }
3231 };
3232
3233 let mut key: Vec<Symbol> =
3234 path.components().map(|comp| Symbol::intern(&comp.as_os_str().to_string_lossy())).collect();
3235
3236 if let Some(last) = path.file_name()
3237 && let Some(stem) = std::path::Path::new(last).file_stem()
3238 {
3239 key.pop();
3240 key.push(Symbol::intern(&stem.to_string_lossy()));
3241 }
3242
3243 Some(key)
3244}
3245
3246fn is_library_item(kind: SyntaxKind) -> bool {
3248 matches!(kind, GLOBAL_CONST | STRUCT_DEF | FUNCTION_DEF | INTERFACE_DEF)
3249}
3250
3251fn is_program_item(kind: SyntaxKind) -> bool {
3253 matches!(
3254 kind,
3255 GLOBAL_CONST
3256 | FUNCTION_DEF
3257 | FINAL_FN_DEF
3258 | STRUCT_DEF
3259 | RECORD_DEF
3260 | INTERFACE_DEF
3261 | MAPPING_DEF
3262 | STORAGE_DEF
3263 | CONSTRUCTOR_DEF
3264 | PROGRAM_DECL
3265 | IMPORT
3266 )
3267}