1use itertools::Itertools as _;
31use snarkvm::prelude::{Address, Signature, TestnetV0};
32
33use leo_ast::{NetworkName, NodeBuilder, NodeID};
34use leo_errors::{Handler, 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(crate::errors::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(crate::errors::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(crate::errors::identifier_too_long(
238 &text,
239 text.len(),
240 MAX_IDENTIFIER_LEN,
241 ident.span,
242 ));
243 }
244 if text.contains("__") {
245 self.handler.emit_err(crate::errors::identifier_cannot_contain_double_underscore(&text, ident.span));
246 }
247 }
248
249 fn validate_definition_identifier(&self, ident: &leo_ast::Identifier) {
253 if ident.name == Symbol::intern("_error") {
255 return;
256 }
257 self.validate_identifier(ident);
258 let text = ident.name.to_string();
259 if text.starts_with('_') {
260 self.handler.emit_err(crate::errors::identifier_cannot_start_with_underscore(ident.span));
261 }
262 if symbol_is_keyword(ident.name) {
263 self.emit_unexpected_str("an identifier", &text, ident.span);
264 }
265 }
266
267 fn to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
273 let ty = match node.kind() {
274 TYPE_PRIMITIVE => self.type_primitive_to_type(node)?,
275 TYPE_LOCATOR => self.type_locator_to_type(node)?,
276 TYPE_PATH => self.type_path_to_type(node)?,
277 TYPE_ARRAY => self.type_array_to_type(node)?,
278 TYPE_VECTOR => self.type_vector_to_type(node)?,
279 TYPE_TUPLE => self.type_tuple_to_type(node)?,
280 TYPE_OPTIONAL => self.type_optional_to_type(node)?,
281 TYPE_FINAL => self.type_final_to_type(node)?,
282 TYPE_MAPPING => self.type_mapping_to_type(node)?,
283 TYPE_DYN_RECORD => leo_ast::Type::DynRecord,
284 ERROR => {
285 leo_ast::Type::Err
287 }
288 kind => panic!("unexpected type node kind: {:?}", kind),
289 };
290 Ok(ty)
291 }
292
293 fn type_primitive_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
295 debug_assert_eq!(node.kind(), TYPE_PRIMITIVE);
296 let prim = tokens(node)
297 .next()
298 .and_then(|t| keyword_to_primitive_type(t.kind()))
299 .expect("TYPE_PRIMITIVE should contain a type keyword");
300 Ok(prim)
301 }
302
303 fn type_locator_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
307 debug_assert_eq!(node.kind(), TYPE_LOCATOR);
308
309 let all_idents: Vec<_> = tokens(node).filter(|t| t.kind() == IDENT).collect();
312 let Some(program_token) = all_idents.first() else {
313 panic!("TYPE_LOCATOR should contain at least a program IDENT: {:?}", node.text())
314 };
315
316 let kw_aleo_token =
318 tokens(node).find(|t| t.kind() == KW_ALEO).expect("TYPE_LOCATOR should contain `aleo` keyword");
319
320 let network_ident = leo_ast::Identifier {
321 name: Symbol::intern("aleo"),
322 span: self.token_span(&kw_aleo_token),
323 id: self.builder.next_id(),
324 };
325
326 let program_ident = self.to_identifier(program_token);
327 let program_id = leo_ast::ProgramId { name: program_ident, network: network_ident };
328
329 if all_idents.len() < 2 {
330 let span = self.content_span(node);
332 let path = leo_ast::Path::new(Some(program_id), Vec::new(), program_ident, span, self.builder.next_id());
333 Ok(leo_ast::CompositeType { path, const_arguments: Vec::new() }.into())
334 } else {
335 let name_token = all_idents.last().unwrap(); let qualifier: Vec<_> = all_idents[1..all_idents.len() - 1].iter().map(|t| self.to_identifier(t)).collect();
339 let type_ident = self.to_identifier(name_token);
340 let path_span = Span::new(program_id.name.span.lo, type_ident.span.hi);
341 let path = leo_ast::Path::new(Some(program_id), qualifier, type_ident, path_span, self.builder.next_id());
342 let (_type_parameters, const_arguments) = self.extract_const_arg_list(node)?;
343 Ok(leo_ast::CompositeType { path, const_arguments }.into())
344 }
345 }
346
347 fn type_path_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
351 debug_assert_eq!(node.kind(), TYPE_PATH);
352
353 let mut path_components = Vec::new();
355
356 for token in tokens(node) {
358 match token.kind() {
359 IDENT => {
360 path_components.push(self.to_identifier(&token));
361 }
362 COLON_COLON | L_BRACKET | R_BRACKET | LT | GT | COMMA | INTEGER => {}
364 kind if kind.is_trivia() => {}
365 kind => panic!("unexpected token in TYPE_PATH: {:?}", kind),
366 }
367 }
368
369 let (_type_parameters, const_arguments) = self.extract_const_arg_list(node)?;
371
372 let name = path_components.pop().expect("TYPE_PATH should have at least one identifier");
375 let path_span =
376 if let Some(first) = path_components.first() { Span::new(first.span.lo, name.span.hi) } else { name.span };
377 let path = leo_ast::Path::new(None, path_components, name, path_span, self.builder.next_id());
378 Ok(leo_ast::CompositeType { path, const_arguments }.into())
379 }
380
381 fn type_array_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
383 debug_assert_eq!(node.kind(), TYPE_ARRAY);
384
385 match children(node).find(|n| n.kind().is_type()) {
386 Some(element_node) => {
387 let element_type = self.to_type(&element_node)?;
388 let length_expr = self.array_length_to_expression(node)?;
389 Ok(leo_ast::ArrayType { element_type: Box::new(element_type), length: Box::new(length_expr) }.into())
390 }
391 None => {
392 let span = self.to_span(node);
394 self.emit_unexpected_str("element type", node.text(), span);
395 Ok(leo_ast::Type::Err)
396 }
397 }
398 }
399
400 fn type_vector_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
402 debug_assert_eq!(node.kind(), TYPE_VECTOR);
403
404 match children(node).find(|n| n.kind().is_type()) {
405 Some(element_node) => {
406 let element_type = self.to_type(&element_node)?;
407 Ok(leo_ast::VectorType { element_type: Box::new(element_type) }.into())
408 }
409 None => {
410 let span = self.to_span(node);
413 self.emit_unexpected_str("element type", node.text(), span);
414 Ok(leo_ast::Type::Err)
415 }
416 }
417 }
418
419 fn array_length_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
421 match children(node).find(|n| n.kind() == ARRAY_LENGTH) {
422 Some(length_node) => self.require_expression(&length_node, "array length"),
423 None => {
424 let span = self.to_span(node);
426 self.emit_unexpected_str("array length", node.text(), span);
427 Ok(self.error_expression(span))
428 }
429 }
430 }
431
432 fn integer_token_to_expression(&self, token: &SyntaxToken) -> Result<leo_ast::Expression> {
434 debug_assert_eq!(token.kind(), INTEGER);
435 let text = token.text();
436 let span = self.token_span(token);
437 let id = self.builder.next_id();
438
439 let suffixes = [
441 ("u128", leo_ast::IntegerType::U128),
442 ("u64", leo_ast::IntegerType::U64),
443 ("u32", leo_ast::IntegerType::U32),
444 ("u16", leo_ast::IntegerType::U16),
445 ("u8", leo_ast::IntegerType::U8),
446 ("i128", leo_ast::IntegerType::I128),
447 ("i64", leo_ast::IntegerType::I64),
448 ("i32", leo_ast::IntegerType::I32),
449 ("i16", leo_ast::IntegerType::I16),
450 ("i8", leo_ast::IntegerType::I8),
451 ];
452
453 for (suffix, int_type) in suffixes {
454 if text.ends_with(suffix) {
455 let value = text.strip_suffix(suffix).unwrap().to_string();
457 return Ok(leo_ast::Literal::integer(int_type, value, span, id).into());
458 }
459 }
460
461 Ok(leo_ast::Literal::unsuffixed(text.to_string(), span, id).into())
463 }
464
465 fn type_tuple_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
467 debug_assert_eq!(node.kind(), TYPE_TUPLE);
468 let span = self.to_span(node);
469
470 let type_nodes: Vec<_> = children(node).filter(|n| n.kind().is_type()).collect();
471
472 if type_nodes.is_empty() {
473 return Ok(leo_ast::Type::Unit);
475 }
476
477 let elements = type_nodes.iter().map(|n| self.to_type(n)).collect::<Result<Vec<_>>>()?;
478
479 if elements.len() == 1 {
480 self.handler.emit_err(crate::errors::tuple_must_have_at_least_two_elements("type", span));
482 return Ok(elements.into_iter().next().unwrap());
484 }
485
486 Ok(leo_ast::TupleType::new(elements).into())
487 }
488
489 fn type_optional_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
491 debug_assert_eq!(node.kind(), TYPE_OPTIONAL);
492
493 let inner_node = children(node).find(|n| n.kind().is_type()).expect("optional type should have inner type");
494
495 let inner = self.to_type(&inner_node)?;
496 Ok(leo_ast::Type::Optional(leo_ast::OptionalType { inner: Box::new(inner) }))
497 }
498
499 fn type_final_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
501 debug_assert_eq!(node.kind(), TYPE_FINAL);
502
503 let type_nodes: Vec<_> = children(node).filter(|n| n.kind().is_type()).collect();
505
506 if type_nodes.is_empty() {
507 return Ok(leo_ast::FutureType::default().into());
509 }
510
511 let types = type_nodes.iter().map(|n| self.to_type(n)).collect::<Result<Vec<_>>>()?;
513
514 Ok(leo_ast::FutureType::new(types, None, true).into())
515 }
516
517 fn type_mapping_to_type(&self, node: &SyntaxNode) -> Result<leo_ast::Type> {
518 debug_assert_eq!(node.kind(), TYPE_MAPPING);
519 let mut type_nodes = children(node).filter(|n| n.kind().is_type());
520 let key = type_nodes.next().map(|n| self.to_type(&n)).transpose()?.unwrap_or(leo_ast::Type::Err);
521 let value = type_nodes.next().map(|n| self.to_type(&n)).transpose()?.unwrap_or(leo_ast::Type::Err);
522 Ok(leo_ast::Type::Mapping(leo_ast::MappingType { key: Box::new(key), value: Box::new(value) }))
523 }
524
525 fn to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
531 let span = self.content_span(node);
532
533 let expr = match node.kind() {
534 LITERAL_FIELD => self.suffixed_literal_to_expression(node, "field", leo_ast::Literal::field)?,
535 LITERAL_GROUP => self.suffixed_literal_to_expression(node, "group", leo_ast::Literal::group)?,
536 LITERAL_SCALAR => self.suffixed_literal_to_expression(node, "scalar", leo_ast::Literal::scalar)?,
537 LITERAL_INT => self.int_literal_to_expression(node)?,
538 LITERAL_STRING => self.string_literal_to_expression(node)?,
539 LITERAL_ADDRESS => self.address_literal_to_expression(node)?,
540 LITERAL_BOOL => self.bool_literal_to_expression(node)?,
541 LITERAL_NONE => leo_ast::Literal::none(span, self.builder.next_id()).into(),
542 LITERAL_IDENT => self.identifier_literal_to_expression(node)?,
543 BINARY_EXPR => self.binary_expr_to_expression(node)?,
544 UNARY_EXPR => self.unary_expr_to_expression(node)?,
545 CALL_EXPR => self.call_expr_to_expression(node)?,
546 DYNAMIC_OP_EXPR => self.dynamic_op_expr_to_expression(node)?,
547 METHOD_CALL_EXPR => self.method_call_expr_to_expression(node)?,
548 FIELD_EXPR => self.field_expr_to_expression(node)?,
549 TUPLE_ACCESS_EXPR => self.tuple_access_expr_to_expression(node)?,
550 INDEX_EXPR => self.index_expr_to_expression(node)?,
551 CAST_EXPR => self.cast_expr_to_expression(node)?,
552 TERNARY_EXPR => self.ternary_expr_to_expression(node)?,
553 ARRAY_EXPR => self.array_expr_to_expression(node)?,
554 REPEAT_EXPR => self.repeat_expr_to_expression(node)?,
555 TUPLE_EXPR => self.tuple_expr_to_expression(node)?,
556 STRUCT_EXPR => self.struct_expr_to_expression(node)?,
557 STRUCT_LOCATOR_EXPR => self.struct_locator_expr_to_expression(node)?,
558 PATH_EXPR => self.path_expr_to_expression(node)?,
559 PATH_LOCATOR_EXPR => self.path_locator_expr_to_expression(node)?,
560 PROGRAM_REF_EXPR => self.program_ref_expr_to_expression(node)?,
561 SELF_EXPR => self.keyword_expr_to_path(node, sym::SelfLower)?,
562 BLOCK_KW_EXPR => self.keyword_expr_to_path(node, sym::block)?,
563 NETWORK_KW_EXPR => self.keyword_expr_to_path(node, sym::network)?,
564 PAREN_EXPR => {
565 if let Some(inner) = children(node).find(|n| n.kind().is_expression()) {
567 self.to_expression(&inner)?
568 } else {
569 self.emit_unexpected_str("expression in parentheses", node.text(), span);
571 self.error_expression(span)
572 }
573 }
574 FINAL_EXPR => self.final_expr_to_expression(node)?,
576 ROOT => {
578 if let Some(inner) = children(node).find(|n| n.kind().is_expression()) {
579 self.to_expression(&inner)?
580 } else {
581 self.error_expression(span)
583 }
584 }
585 ERROR => self.error_expression(span),
588 kind => panic!("unexpected expression kind: {:?}", kind),
589 };
590
591 Ok(expr)
592 }
593
594 fn suffixed_literal_to_expression(
596 &self,
597 node: &SyntaxNode,
598 suffix: &str,
599 ctor: fn(String, Span, leo_ast::NodeID) -> leo_ast::Literal,
600 ) -> Result<leo_ast::Expression> {
601 let span = self.content_span(node);
602 let id = self.builder.next_id();
603 let token = tokens(node).next().expect("literal node should have a token");
604 let text = token.text();
605 self.validate_hexbin_literal(text, suffix.len() as u32, span);
606 let value = text.strip_suffix(suffix).unwrap();
607 Ok(ctor(value.to_string(), span, id).into())
608 }
609
610 fn int_literal_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
612 let token = tokens(node).next().expect("LITERAL_INT should have a token");
613 self.integer_token_to_expression(&token)
614 }
615
616 fn string_literal_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
618 let span = self.content_span(node);
619 let id = self.builder.next_id();
620 let token = tokens(node).next().expect("LITERAL_STRING should have a token");
621 Ok(leo_ast::Literal::string(token.text().to_string(), span, id).into())
622 }
623
624 fn identifier_literal_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
626 let span = self.content_span(node);
627 let id = self.builder.next_id();
628 let token = tokens(node).next().expect("LITERAL_IDENT should have a token");
629 let text = token.text();
631 let content = &text[1..text.len() - 1];
632 Ok(leo_ast::Literal::identifier(content.to_string(), span, id).into())
633 }
634
635 fn address_literal_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
637 let span = self.content_span(node);
638 let id = self.builder.next_id();
639 let token = tokens(node).next().expect("LITERAL_ADDRESS should have a token");
640 let text = token.text();
641 if !text.contains(".aleo") && text.parse::<Address<TestnetV0>>().is_err() {
643 self.handler.emit_err(crate::errors::invalid_address_lit(text, span));
644 }
645 Ok(leo_ast::Literal::address(text.to_string(), span, id).into())
646 }
647
648 fn bool_literal_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
650 let span = self.content_span(node);
651 let id = self.builder.next_id();
652 let token = tokens(node).next().expect("LITERAL_BOOL should have a token");
653 let value = token.kind() == KW_TRUE;
654 Ok(leo_ast::Literal::boolean(value, span, id).into())
655 }
656
657 fn binary_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
659 debug_assert_eq!(node.kind(), BINARY_EXPR);
660 let span = self.content_span(node);
661 let id = self.builder.next_id();
662
663 let mut operands = children(node).filter(|n| n.kind().is_expression() || n.kind().is_type());
664
665 let op_token = match tokens(node).find(|t| t.kind().is_operator() || t.kind() == KW_AS) {
667 Some(token) => token,
668 None => {
669 self.emit_unexpected_str("operator in binary expression", node.text(), span);
670 return Ok(self.error_expression(span));
671 }
672 };
673
674 let op = token_to_binary_op(op_token.kind());
675
676 let left = match operands.next() {
678 Some(left_node) => self.to_expression(&left_node)?,
679 None => {
680 self.emit_unexpected_str("left operand in binary expression", node.text(), span);
681 return Ok(self.error_expression(span));
682 }
683 };
684
685 if op_token.kind() == KW_AS {
687 self.emit_unexpected_str("cast expression", "binary AS expression", span);
688 return Ok(self.error_expression(span));
689 }
690
691 let right = match operands.next() {
693 Some(right_node) => self.to_expression(&right_node)?,
694 None => {
695 self.emit_unexpected_str("right operand in binary expression", node.text(), span);
696 return Ok(self.error_expression(span));
697 }
698 };
699
700 Ok(leo_ast::BinaryExpression { left, right, op, span, id }.into())
701 }
702
703 fn unary_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
705 debug_assert_eq!(node.kind(), UNARY_EXPR);
706 let span = self.content_span(node);
707 let id = self.builder.next_id();
708
709 let Some(op_token) = tokens(node).find(|t| matches!(t.kind(), BANG | MINUS)) else {
711 self.emit_unexpected_str("operator in unary expression", node.text(), span);
712 return Ok(self.error_expression(span));
713 };
714
715 let op = if op_token.kind() == BANG { leo_ast::UnaryOperation::Not } else { leo_ast::UnaryOperation::Negate };
716
717 let Some(operand) = children(node).find(|n| n.kind().is_expression()) else {
719 self.emit_unexpected_str("operand in unary expression", node.text(), span);
720 return Ok(self.error_expression(span));
721 };
722
723 let mut receiver = self.to_expression(&operand)?;
724
725 if op == leo_ast::UnaryOperation::Negate
727 && let leo_ast::Expression::Literal(leo_ast::Literal {
728 variant:
729 leo_ast::LiteralVariant::Integer(_, ref mut string)
730 | leo_ast::LiteralVariant::Field(ref mut string)
731 | leo_ast::LiteralVariant::Group(ref mut string)
732 | leo_ast::LiteralVariant::Scalar(ref mut string),
733 span: ref mut lit_span,
734 ..
735 }) = receiver
736 && !string.starts_with('-')
737 {
738 string.insert(0, '-');
739 *lit_span = span;
740 return Ok(receiver);
741 }
742
743 Ok(leo_ast::UnaryExpression { receiver, op, span, id }.into())
744 }
745
746 fn extract_const_arg_list(&self, node: &SyntaxNode) -> Result<ConstArgList> {
753 let mut type_parameters = Vec::new();
754 let mut const_arguments = Vec::new();
755 if let Some(arg_list) = children(node).find(|n| n.kind() == CONST_ARG_LIST) {
756 for child in children(&arg_list) {
757 if child.kind() == DYNAMIC_CALL_RETURN_TYPE {
758 if let Some(type_node) = children(&child).find(|n| n.kind().is_type()) {
761 let span = self.content_span(&child);
762 let ty = self.to_type(&type_node)?;
763 type_parameters.push((ty, span));
764 }
765 } else if child.kind().is_type() {
766 let span = self.content_span(&child);
767 let ty = self.to_type(&child)?;
768 type_parameters.push((ty, span));
769 } else if child.kind().is_expression() {
770 let expr = self.to_expression(&child)?;
771 const_arguments.push(expr);
772 }
773 }
774 }
775 Ok((type_parameters, const_arguments))
776 }
777
778 fn extract_dynamic_call_types(
788 &self,
789 callee_node: &SyntaxNode,
790 type_parameters: &[(leo_ast::Type, Span)],
791 ) -> Result<(AnnotatedTypes, AnnotatedTypes)> {
792 let Some(arg_list) = children(callee_node).find(|n| n.kind() == CONST_ARG_LIST) else {
793 return Ok((Vec::new(), Vec::new()));
794 };
795
796 let mut all_entries = Vec::new();
798
799 for child in children(&arg_list) {
800 if child.kind() == DYNAMIC_CALL_RETURN_TYPE {
801 let mode = tokens(&child).find_map(|tok| token_kind_to_mode(tok.kind())).unwrap_or(leo_ast::Mode::None);
802 all_entries.push(mode);
803 } else if child.kind().is_type() {
804 all_entries.push(leo_ast::Mode::None);
805 }
806 }
807
808 if type_parameters.is_empty() {
810 return Ok((Vec::new(), Vec::new()));
811 }
812
813 let mut input_types = Vec::new();
814 let mut return_types = Vec::new();
815
816 let last_idx = type_parameters.len() - 1;
817 for (i, ((ty, sp), mode)) in type_parameters.iter().zip(all_entries.iter()).enumerate() {
818 if i < last_idx {
819 input_types.push((*mode, ty.clone(), *sp));
821 } else {
822 match ty {
827 leo_ast::Type::Unit => {}
828 leo_ast::Type::Tuple(tuple) => {
829 for elem in tuple.elements() {
830 return_types.push((*mode, elem.clone(), *sp));
831 }
832 }
833 _ => {
834 return_types.push((*mode, ty.clone(), *sp));
835 }
836 }
837 }
838 }
839
840 Ok((input_types, return_types))
841 }
842
843 fn call_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
845 debug_assert_eq!(node.kind(), CALL_EXPR);
846 let span = self.content_span(node);
847 let id = self.builder.next_id();
848
849 let mut child_iter = children(node);
851 let callee_node = child_iter.next().expect("call expr should have callee");
852
853 let function = match callee_node.kind() {
854 PATH_LOCATOR_EXPR => self.locator_tokens_to_path(&callee_node)?,
855 _ => self.path_expr_to_path(&callee_node)?,
856 };
857
858 let arguments = children(node)
860 .skip(1) .filter(|n| n.kind().is_expression())
862 .map(|n| self.to_expression(&n))
863 .collect::<Result<Vec<_>>>()?;
864
865 let (type_parameters, const_arguments) = self.extract_const_arg_list(&callee_node)?;
868
869 if function.user_program().is_none() && function.qualifier().len() == 1 {
873 let module = function.qualifier()[0].name;
874 let name = function.identifier().name;
875 if let Some(intrinsic_name) = leo_ast::Intrinsic::convert_path_symbols(module, name) {
876 return Ok(leo_ast::IntrinsicExpression {
877 name: intrinsic_name,
878 type_parameters,
879 input_types: Vec::new(),
880 return_types: Vec::new(),
881 arguments,
882 span,
883 id,
884 }
885 .into());
886 }
887 }
888
889 if function.user_program().is_none() && function.qualifier().is_empty() {
892 let name = function.identifier().name;
893 if leo_ast::Intrinsic::from_symbol(name, &type_parameters).is_some() {
894 let (input_types, return_types) = if name == leo_span::sym::_dynamic_call {
897 self.extract_dynamic_call_types(&callee_node, &type_parameters)?
898 } else {
899 (Vec::new(), Vec::new())
900 };
901 return Ok(leo_ast::IntrinsicExpression {
902 name,
903 type_parameters,
904 input_types,
905 return_types,
906 arguments,
907 span,
908 id,
909 }
910 .into());
911 }
912 }
913
914 Ok(leo_ast::CallExpression { function, const_arguments, arguments, span, id }.into())
915 }
916
917 fn dynamic_op_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
924 debug_assert_eq!(node.kind(), DYNAMIC_OP_EXPR);
925 let span = self.content_span(node);
926 let id = self.builder.next_id();
927
928 let interface = children(node)
929 .filter(|n| n.kind().is_type())
930 .map(|n| self.to_type(&n))
931 .next()
932 .expect("Parser guarantees a type")?;
933
934 let separator_offset = tokens(node).filter(|t| t.kind() == COLON_COLON).last().map(|t| t.text_range().start());
937
938 let dot_offset = tokens(node).find(|t| t.kind() == DOT).map(|t| t.text_range().start());
940
941 let has_call_parens =
943 tokens(node).any(|t| t.kind() == L_PAREN && Some(t.text_range().start()) > separator_offset);
944
945 let expr_children: Vec<_> = children(node).filter(|n| n.kind().is_expression()).collect();
946
947 let (pre_sep, post_sep): (Vec<_>, Vec<_>) = expr_children.iter().partition(|child| match separator_offset {
948 Some(sep_off) => child.text_range().start() < sep_off,
949 None => true,
950 });
951
952 let target = match pre_sep.first() {
953 Some(target_node) => self.to_expression(target_node)?,
954 None => self.error_expression(span),
955 };
956
957 let network =
958 if let Some(network_node) = pre_sep.get(1) { Some(self.to_expression(network_node)?) } else { None };
959
960 let arguments = post_sep.iter().map(|n| self.to_expression(n)).collect::<Result<Vec<_>>>()?;
961
962 let kind = if let Some(dot_pos) = dot_offset {
963 let member = tokens(node)
965 .find(|t| t.kind() == IDENT && t.text_range().start() < dot_pos)
966 .map(|t| self.to_identifier(&t))
967 .unwrap_or_else(|| self.error_identifier(span));
968 let op = tokens(node)
969 .find(|t| t.kind() == IDENT && t.text_range().start() > dot_pos)
970 .map(|t| self.to_identifier(&t))
971 .unwrap_or_else(|| self.error_identifier(span));
972 leo_ast::DynamicOpKind::Op { member, op, arguments }
973 } else if has_call_parens {
974 let function = tokens(node)
976 .find(|t| t.kind() == IDENT)
977 .map(|t| self.to_identifier(&t))
978 .unwrap_or_else(|| self.error_identifier(span));
979 leo_ast::DynamicOpKind::Call { function, arguments }
980 } else {
981 let storage = tokens(node)
983 .find(|t| t.kind() == IDENT)
984 .map(|t| self.to_identifier(&t))
985 .unwrap_or_else(|| self.error_identifier(span));
986 leo_ast::DynamicOpKind::Read { storage }
987 };
988
989 Ok(leo_ast::DynamicOpExpression { interface, target_program: target, network, kind, span, id }.into())
990 }
991
992 fn method_call_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
996 debug_assert_eq!(node.kind(), METHOD_CALL_EXPR);
997 let span = self.content_span(node);
998 let id = self.builder.next_id();
999
1000 let mut expr_children = children(node).filter(|n| n.kind().is_expression());
1002 let receiver = match expr_children.next() {
1003 Some(receiver_node) => self.to_expression(&receiver_node)?,
1004 None => {
1005 self.emit_unexpected_str("receiver in method call", node.text(), span);
1006 return Ok(self.error_expression(span));
1007 }
1008 };
1009
1010 let method_name = match find_name_after_dot(node) {
1016 Some(method_token) if method_token.kind() == IDENT => self.to_identifier(&method_token),
1017 Some(method_token) => {
1018 let token_span = self.token_span(&method_token);
1019 self.emit_unexpected_str("identifier", method_token.text(), token_span);
1020 self.error_identifier(token_span)
1021 }
1022 None => {
1023 self.emit_unexpected_str("method name in method call", node.text(), span);
1024 return Ok(self.error_expression(span));
1025 }
1026 };
1027
1028 let mut args: Vec<_> = expr_children.map(|n| self.to_expression(&n)).collect::<Result<Vec<_>>>()?;
1030
1031 if args.is_empty() {
1033 if let Some(op) = leo_ast::UnaryOperation::from_symbol(method_name.name) {
1034 return Ok(leo_ast::UnaryExpression { span, op, receiver, id }.into());
1035 }
1036 } else if args.len() == 1
1037 && let Some(op) = leo_ast::BinaryOperation::from_symbol(method_name.name)
1038 {
1039 return Ok(leo_ast::BinaryExpression { span, op, left: receiver, right: args.pop().unwrap(), id }.into());
1040 }
1041
1042 let method = method_name.name;
1048 let all_args = || std::iter::once(receiver.clone()).chain(args.clone()).collect::<Vec<_>>();
1049
1050 let intrinsic_name = match args.len() {
1052 2 => leo_ast::Intrinsic::convert_path_symbols(sym::signature, method),
1053 0 => leo_ast::Intrinsic::convert_path_symbols(sym::Final, method)
1054 .or_else(|| leo_ast::Intrinsic::convert_path_symbols(sym::Optional, method)),
1055 1 => leo_ast::Intrinsic::convert_path_symbols(sym::Optional, method),
1056 _ => None,
1057 };
1058 if let Some(intrinsic_name) = intrinsic_name {
1059 return Ok(self.intrinsic_expression(intrinsic_name, all_args(), span));
1060 }
1061
1062 if method == sym::get && args.len() == 1 {
1065 return Ok(self.intrinsic_expression(Symbol::intern("__unresolved_get"), all_args(), span));
1066 }
1067 if method == sym::set && args.len() == 2 {
1068 return Ok(self.intrinsic_expression(Symbol::intern("__unresolved_set"), all_args(), span));
1069 }
1070
1071 for module in [sym::Vector, sym::Mapping] {
1073 if let Some(intrinsic_name) = leo_ast::Intrinsic::convert_path_symbols(module, method) {
1074 return Ok(self.intrinsic_expression(intrinsic_name, all_args(), span));
1075 }
1076 }
1077
1078 self.handler.emit_err(crate::errors::invalid_method_call(receiver, method_name, args.len(), span));
1080 Ok(self.error_expression(span))
1081 }
1082
1083 fn tuple_access_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1085 debug_assert_eq!(node.kind(), TUPLE_ACCESS_EXPR);
1086 let span = self.content_span(node);
1087 let id = self.builder.next_id();
1088
1089 let inner = if let Some(inner_node) = children(node).find(|n| n.kind().is_expression()) {
1090 self.to_expression(&inner_node)?
1091 } else {
1092 self.emit_unexpected_str("expression in tuple access", node.text(), span);
1093 return Ok(self.error_expression(span));
1094 };
1095
1096 let index_token = match tokens(node).find(|t| t.kind() == INTEGER) {
1097 Some(token) => token,
1098 None => {
1099 self.emit_unexpected_str("tuple index", node.text(), span);
1100 return Ok(self.error_expression(span));
1101 }
1102 };
1103
1104 let index_text = index_token.text().replace('_', "");
1105 let index: usize = match index_text.parse() {
1106 Ok(idx) => idx,
1107 Err(_) => {
1108 self.emit_unexpected_str("valid tuple index", index_text, span);
1109 return Ok(self.error_expression(span));
1110 }
1111 };
1112 Ok(leo_ast::TupleAccess { tuple: inner, index: index.into(), span, id }.into())
1113 }
1114
1115 fn field_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1117 debug_assert_eq!(node.kind(), FIELD_EXPR);
1118 let span = self.content_span(node);
1119 let id = self.builder.next_id();
1120
1121 let (inner, first_child_kind) = match children(node).find(|n| n.kind().is_expression()) {
1123 Some(n) => {
1124 let kind = n.kind();
1125 (self.to_expression(&n)?, kind)
1126 }
1127 None => {
1128 self.emit_unexpected_str("expression in field access", node.text(), span);
1129 return Ok(self.error_expression(span));
1130 }
1131 };
1132
1133 let field_token = match find_name_after_dot(node) {
1136 Some(token) => token,
1137 None => {
1138 self.emit_unexpected_str("field name in field access", node.text(), span);
1139 return Ok(self.error_expression(span));
1140 }
1141 };
1142
1143 if field_token.kind() == KW_ALEO
1147 && let leo_ast::Expression::Path(ref path) = inner
1148 && path.user_program().is_none()
1149 && path.qualifier().is_empty()
1150 {
1151 let full_name = format!("{}.aleo", path.identifier().name);
1152 return Ok(leo_ast::Literal::address(full_name, span, id).into());
1153 }
1154
1155 let field_name = Symbol::intern(field_token.text());
1157
1158 let special = match (first_child_kind, field_name) {
1159 (SELF_EXPR, sym::address) => Some(sym::_self_address),
1160 (SELF_EXPR, sym::caller) => Some(sym::_self_caller),
1161 (SELF_EXPR, sym::checksum) => Some(sym::_self_checksum),
1162 (SELF_EXPR, sym::edition) => Some(sym::_self_edition),
1163 (SELF_EXPR, sym::id) => Some(sym::_self_id),
1164 (SELF_EXPR, sym::program_owner) => Some(sym::_self_program_owner),
1165 (SELF_EXPR, sym::signer) => Some(sym::_self_signer),
1166 (BLOCK_KW_EXPR, sym::height) => Some(sym::_block_height),
1167 (BLOCK_KW_EXPR, sym::timestamp) => Some(sym::_block_timestamp),
1168 (NETWORK_KW_EXPR, sym::id) => Some(sym::_network_id),
1169 (SELF_EXPR | BLOCK_KW_EXPR | NETWORK_KW_EXPR, _) => {
1170 self.handler.emit_err(crate::errors::custom("Unsupported special access", span));
1171 return Ok(self.error_expression(span));
1172 }
1173 _ => None,
1174 };
1175
1176 if let Some(intrinsic_name) = special {
1177 return Ok(self.intrinsic_expression(intrinsic_name, Vec::new(), span));
1178 }
1179
1180 let name = leo_ast::Identifier {
1182 name: Symbol::intern(field_token.text()),
1183 span: self.token_span(&field_token),
1184 id: self.builder.next_id(),
1185 };
1186 Ok(leo_ast::MemberAccess { inner, name, span, id }.into())
1187 }
1188
1189 fn index_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1191 debug_assert_eq!(node.kind(), INDEX_EXPR);
1192 let span = self.content_span(node);
1193 let id = self.builder.next_id();
1194
1195 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1196
1197 let array = match exprs.next() {
1198 Some(n) => self.to_expression(&n)?,
1199 None => {
1200 self.emit_unexpected_str("array in index expression", node.text(), span);
1201 return Ok(self.error_expression(span));
1202 }
1203 };
1204
1205 let index = match exprs.next() {
1206 Some(n) => self.to_expression(&n)?,
1207 None => {
1208 self.emit_unexpected_str("index in index expression", node.text(), span);
1209 return Ok(self.error_expression(span));
1210 }
1211 };
1212
1213 Ok(leo_ast::ArrayAccess { array, index, span, id }.into())
1214 }
1215
1216 fn cast_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1218 debug_assert_eq!(node.kind(), CAST_EXPR);
1219 let span = self.content_span(node);
1220 let id = self.builder.next_id();
1221
1222 let Some(expr_node) = children(node).find(|n| n.kind().is_expression()) else {
1224 self.emit_unexpected_str("expression in cast", node.text(), span);
1225 return Ok(self.error_expression(span));
1226 };
1227 let expression = self.to_expression(&expr_node)?;
1228
1229 let Some(type_node) = children(node).find(|n| n.kind().is_type()) else {
1231 self.emit_unexpected_str("type in cast expression", node.text(), span);
1232 return Ok(self.error_expression(span));
1233 };
1234 let type_ = self.to_type(&type_node)?;
1235
1236 Ok(leo_ast::CastExpression { expression, type_, span, id }.into())
1237 }
1238
1239 fn ternary_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1241 debug_assert_eq!(node.kind(), TERNARY_EXPR);
1242 let span = self.content_span(node);
1243 let id = self.builder.next_id();
1244
1245 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1246
1247 let condition = match exprs.next() {
1248 Some(n) => self.to_expression(&n)?,
1249 None => {
1250 self.emit_unexpected_str("condition in ternary expression", node.text(), span);
1251 return Ok(self.error_expression(span));
1252 }
1253 };
1254
1255 let if_true = match exprs.next() {
1256 Some(n) => self.to_expression(&n)?,
1257 None => {
1258 self.emit_unexpected_str("true branch in ternary expression", node.text(), span);
1259 return Ok(self.error_expression(span));
1260 }
1261 };
1262
1263 let if_false = match exprs.next() {
1264 Some(n) => self.to_expression(&n)?,
1265 None => {
1266 self.emit_unexpected_str("false branch in ternary expression", node.text(), span);
1267 return Ok(self.error_expression(span));
1268 }
1269 };
1270
1271 Ok(leo_ast::TernaryExpression { condition, if_true, if_false, span, id }.into())
1272 }
1273
1274 fn array_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1276 debug_assert_eq!(node.kind(), ARRAY_EXPR);
1277 let span = self.content_span(node);
1278 let id = self.builder.next_id();
1279
1280 let elements = children(node)
1281 .filter(|n| n.kind().is_expression())
1282 .map(|n| self.to_expression(&n))
1283 .collect::<Result<Vec<_>>>()?;
1284
1285 Ok(leo_ast::ArrayExpression { elements, span, id }.into())
1286 }
1287
1288 fn repeat_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1290 debug_assert_eq!(node.kind(), REPEAT_EXPR);
1291 let span = self.content_span(node);
1292 let id = self.builder.next_id();
1293
1294 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1295 let expr = match exprs.next() {
1296 Some(n) => self.to_expression(&n)?,
1297 None => {
1298 self.emit_unexpected_str("expression in repeat", node.text(), span);
1299 return Ok(self.error_expression(span));
1300 }
1301 };
1302 let count = match exprs.next() {
1303 Some(n) => self.to_expression(&n)?,
1304 None => {
1305 self.emit_unexpected_str("repeat count", node.text(), span);
1306 return Ok(self.error_expression(span));
1307 }
1308 };
1309
1310 Ok(leo_ast::RepeatExpression { expr, count, span, id }.into())
1311 }
1312
1313 fn tuple_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1315 debug_assert_eq!(node.kind(), TUPLE_EXPR);
1316 let span = self.content_span(node);
1317 let id = self.builder.next_id();
1318
1319 let elements: Vec<_> = children(node)
1320 .filter(|n| n.kind().is_expression())
1321 .map(|n| self.to_expression(&n))
1322 .collect::<Result<Vec<_>>>()?;
1323
1324 match elements.len() {
1325 0 => {
1326 self.handler.emit_err(crate::errors::tuple_must_have_at_least_two_elements("expression", span));
1328 Ok(leo_ast::UnitExpression { span, id }.into())
1330 }
1331 1 => {
1332 self.handler.emit_err(crate::errors::tuple_must_have_at_least_two_elements("expression", span));
1334 Ok(elements.into_iter().next().unwrap())
1336 }
1337 _ => Ok(leo_ast::TupleExpression { elements, span, id }.into()),
1338 }
1339 }
1340
1341 fn composite_expression_from_path(
1344 &self,
1345 node: &SyntaxNode,
1346 path: leo_ast::Path,
1347 span: Span,
1348 id: leo_ast::NodeID,
1349 ) -> Result<leo_ast::Expression> {
1350 let members = children(node)
1351 .filter(|n| matches!(n.kind(), STRUCT_FIELD_INIT | STRUCT_FIELD_SHORTHAND))
1352 .map(|n| self.struct_field_init_to_member(&n))
1353 .collect::<Result<Vec<_>>>()?;
1354 let (_type_parameters, const_arguments) = self.extract_const_arg_list(node)?;
1355 Ok(leo_ast::CompositeExpression { path, const_arguments, members, span, id }.into())
1356 }
1357
1358 fn struct_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1360 debug_assert_eq!(node.kind(), STRUCT_EXPR);
1361 let span = self.content_span(node);
1362 let id = self.builder.next_id();
1363 let path = self.struct_expr_to_path(node)?;
1364 self.composite_expression_from_path(node, path, span, id)
1365 }
1366
1367 fn struct_expr_to_path(&self, node: &SyntaxNode) -> Result<leo_ast::Path> {
1369 let fallback_span = self.content_span(node);
1370
1371 let mut path_components = Vec::new();
1373 for token in tokens(node) {
1374 if token.kind() == L_BRACE {
1375 break;
1376 }
1377 if token.kind() == IDENT {
1378 path_components.push(self.to_identifier(&token));
1379 }
1380 }
1381
1382 let path_span = match (path_components.first(), path_components.last()) {
1383 (Some(first), Some(last)) => Span::new(first.span.lo, last.span.hi),
1384 _ => fallback_span,
1385 };
1386
1387 let name = match path_components.pop() {
1388 Some(name) => name,
1389 None => {
1390 self.emit_unexpected_str("type name in struct expression", node.text(), fallback_span);
1391 self.error_identifier(fallback_span)
1392 }
1393 };
1394 Ok(leo_ast::Path::new(None, path_components, name, path_span, self.builder.next_id()))
1395 }
1396
1397 fn struct_locator_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1399 let span = self.content_span(node);
1400 let id = self.builder.next_id();
1401 let path = self.locator_tokens_to_path(node)?;
1402 self.composite_expression_from_path(node, path, span, id)
1403 }
1404
1405 fn path_locator_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1407 let path = self.locator_tokens_to_path(node)?;
1408 Ok(leo_ast::Expression::Path(path))
1409 }
1410
1411 fn locator_tokens_to_path(&self, node: &SyntaxNode) -> Result<leo_ast::Path> {
1418 let span = self.to_span(node);
1419 let all_idents: Vec<_> = tokens(node).filter(|t| t.kind() == IDENT).collect();
1420
1421 let program_ident = match all_idents.first() {
1423 Some(t) => self.to_identifier(t),
1424 None => {
1425 self.emit_unexpected_str("program name", node.text(), span);
1426 self.error_identifier(span)
1427 }
1428 };
1429
1430 let network_ident = leo_ast::Identifier {
1432 name: Symbol::intern("aleo"),
1433 span: tokens(node).find(|t| t.kind() == KW_ALEO).map(|t| self.token_span(&t)).unwrap_or(span),
1434 id: self.builder.next_id(),
1435 };
1436
1437 let program = leo_ast::ProgramId { name: program_ident, network: network_ident };
1439
1440 let (qualifier, name) = if all_idents.len() < 2 {
1444 self.emit_unexpected_str("identifier", node.text(), span);
1445 (Vec::new(), self.error_identifier(span))
1446 } else {
1447 let name = self.to_identifier(all_idents.last().unwrap()); let qualifier: Vec<_> = all_idents[1..all_idents.len() - 1].iter().map(|t| self.to_identifier(t)).collect();
1449 (qualifier, name)
1450 };
1451
1452 let path_span = Span::new(program.name.span.lo, name.span.hi);
1453 Ok(leo_ast::Path::new(Some(program), qualifier, name, path_span, self.builder.next_id()))
1454 }
1455
1456 fn struct_field_init_to_member(&self, node: &SyntaxNode) -> Result<leo_ast::CompositeFieldInitializer> {
1458 debug_assert!(matches!(node.kind(), STRUCT_FIELD_INIT | STRUCT_FIELD_SHORTHAND));
1459 let span = self.content_span(node);
1460 let id = self.builder.next_id();
1461
1462 let Some(ident_token) = tokens(node).find(|t| t.kind() == IDENT) else {
1463 self.emit_unexpected_str("identifier in struct field", node.text(), span);
1464 return Ok(leo_ast::CompositeFieldInitializer {
1465 identifier: self.error_identifier(span),
1466 expression: None,
1467 span,
1468 id,
1469 });
1470 };
1471 let identifier = self.to_identifier(&ident_token);
1472
1473 let expression = if node.kind() == STRUCT_FIELD_INIT {
1474 children(node).find(|n| n.kind().is_expression()).map(|n| self.to_expression(&n)).transpose()?
1475 } else {
1476 None
1477 };
1478
1479 Ok(leo_ast::CompositeFieldInitializer { identifier, expression, span, id })
1480 }
1481
1482 fn program_ref_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1484 debug_assert_eq!(node.kind(), PROGRAM_REF_EXPR);
1485 let span = self.content_span(node);
1486 let id = self.builder.next_id();
1487 let text: String = tokens(node).map(|t| t.text().to_string()).collect();
1488 Ok(leo_ast::Literal::address(text, span, id).into())
1489 }
1490
1491 fn path_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1493 debug_assert_eq!(node.kind(), PATH_EXPR);
1494
1495 let path = self.path_expr_to_path(node)?;
1496 let span = self.trimmed_span(node);
1497 let id = self.builder.next_id();
1498
1499 if path.user_program().is_none()
1501 && path.qualifier().len() == 1
1502 && path.qualifier()[0].name == sym::group
1503 && path.identifier().name == sym::GEN
1504 {
1505 return Ok(self.intrinsic_expression(sym::_group_gen, Vec::new(), span));
1506 }
1507
1508 if path.user_program().is_none() && path.qualifier().is_empty() {
1511 let name_text = path.identifier().name.to_string();
1512 if name_text.starts_with("sign1") && name_text.parse::<Signature<TestnetV0>>().is_ok() {
1513 return Ok(leo_ast::Literal::signature(name_text, span, id).into());
1514 }
1515 if name_text.starts_with('_') {
1518 self.handler.emit_err(crate::errors::identifier_cannot_start_with_underscore(span));
1519 return Ok(self.error_expression(span));
1520 }
1521 }
1522
1523 Ok(leo_ast::Expression::Path(path))
1524 }
1525
1526 fn keyword_expr_to_path(&self, node: &SyntaxNode, name: Symbol) -> Result<leo_ast::Expression> {
1528 let span = self.trimmed_span(node);
1529 let ident = leo_ast::Identifier { name, span, id: self.builder.next_id() };
1530 let path = leo_ast::Path::new(None, Vec::new(), ident, span, self.builder.next_id());
1531 Ok(leo_ast::Expression::Path(path))
1532 }
1533
1534 fn final_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1536 debug_assert_eq!(node.kind(), FINAL_EXPR);
1537 let span = self.content_span(node);
1538 let id = self.builder.next_id();
1539
1540 if let Some(block_node) = children(node).find(|n| n.kind() == BLOCK) {
1542 let block = self.to_block(&block_node)?;
1543 Ok(leo_ast::AsyncExpression { block, span, id }.into())
1544 } else {
1545 self.emit_unexpected_str("block in final expression", node.text(), span);
1547 Ok(self.error_expression(span))
1548 }
1549 }
1550
1551 fn path_expr_to_path(&self, node: &SyntaxNode) -> Result<leo_ast::Path> {
1559 let span = self.trimmed_span(node);
1560
1561 let mut path_components = Vec::new();
1563 for token in tokens(node) {
1564 match token.kind() {
1565 IDENT => {
1566 let text = token.text();
1567 if text.contains("::") {
1571 let token_span = self.token_span(&token);
1572 let mut offset = token_span.lo;
1573 for (i, segment) in text.split("::").enumerate() {
1574 if i > 0 {
1575 offset += 2; }
1577 let seg_span = Span::new(offset, offset + segment.len() as u32);
1578 path_components.push(leo_ast::Identifier {
1579 name: Symbol::intern(segment),
1580 span: seg_span,
1581 id: self.builder.next_id(),
1582 });
1583 offset += segment.len() as u32;
1584 }
1585 } else {
1586 path_components.push(self.to_identifier(&token));
1587 }
1588 }
1589 kind => {
1590 if let Some(name) = keyword_to_path_symbol(kind) {
1591 path_components.push(leo_ast::Identifier {
1592 name,
1593 span: self.token_span(&token),
1594 id: self.builder.next_id(),
1595 });
1596 }
1597 }
1598 }
1599 }
1600
1601 let name = match path_components.pop() {
1602 Some(name) => name,
1603 None => {
1604 self.emit_unexpected_str("identifier in path", node.text(), span);
1605 self.error_identifier(span)
1606 }
1607 };
1608 Ok(leo_ast::Path::new(None, path_components, name, span, self.builder.next_id()))
1609 }
1610
1611 fn to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1617 let span = self.to_span(node);
1618 let id = self.builder.next_id();
1619
1620 let stmt = match node.kind() {
1621 LET_STMT => self.let_stmt_to_statement(node)?,
1622 CONST_STMT => self.const_stmt_to_statement(node)?,
1623 RETURN_STMT => self.return_stmt_to_statement(node)?,
1624 EXPR_STMT => self.expr_stmt_to_statement(node)?,
1625 ASSIGN_STMT => self.simple_assign_to_statement(node)?,
1626 COMPOUND_ASSIGN_STMT => self.compound_assign_to_statement(node)?,
1627 IF_STMT => self.if_stmt_to_statement(node)?,
1628 FOR_STMT | FOR_INCLUSIVE_STMT => self.for_stmt_to_statement(node)?,
1629 BLOCK => self.to_block(node)?.into(),
1630 ASSERT_STMT => {
1631 let expression = self.require_expression(node, "expression in assert")?;
1632 leo_ast::AssertStatement { variant: leo_ast::AssertVariant::Assert(expression), span, id }.into()
1633 }
1634 ASSERT_EQ_STMT => {
1635 self.assert_binary_to_statement(node, "assert_eq", span, id, leo_ast::AssertVariant::AssertEq)?
1636 }
1637 ASSERT_NEQ_STMT => {
1638 self.assert_binary_to_statement(node, "assert_neq", span, id, leo_ast::AssertVariant::AssertNeq)?
1639 }
1640 ROOT => {
1642 if let Some(inner) = children(node).find(|n| n.kind().is_statement()) {
1643 self.to_statement(&inner)?
1644 } else {
1645 leo_ast::ExpressionStatement { expression: self.error_expression(span), span, id }.into()
1647 }
1648 }
1649 ERROR => leo_ast::ExpressionStatement { expression: self.error_expression(span), span, id }.into(),
1652 kind => panic!("unexpected statement kind: {:?}", kind),
1653 };
1654
1655 Ok(stmt)
1656 }
1657
1658 fn assert_binary_to_statement(
1660 &self,
1661 node: &SyntaxNode,
1662 label: &str,
1663 span: Span,
1664 id: leo_ast::NodeID,
1665 make_variant: fn(leo_ast::Expression, leo_ast::Expression) -> leo_ast::AssertVariant,
1666 ) -> Result<leo_ast::Statement> {
1667 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1668 let e0 = match exprs.next() {
1669 Some(expr) => self.to_expression(&expr)?,
1670 None => {
1671 self.emit_unexpected_str(&format!("first expression in {label}"), node.text(), span);
1672 self.error_expression(span)
1673 }
1674 };
1675 let e1 = match exprs.next() {
1676 Some(expr) => self.to_expression(&expr)?,
1677 None => {
1678 self.emit_unexpected_str(&format!("second expression in {label}"), node.text(), span);
1679 self.error_expression(span)
1680 }
1681 };
1682 Ok(leo_ast::AssertStatement { variant: make_variant(e0, e1), span, id }.into())
1683 }
1684
1685 fn to_block(&self, node: &SyntaxNode) -> Result<leo_ast::Block> {
1687 debug_assert_eq!(node.kind(), BLOCK);
1688 let span = self.to_span(node);
1689 let id = self.builder.next_id();
1690
1691 let statements = children(node)
1692 .filter(|n| n.kind().is_statement())
1693 .map(|n| self.to_statement(&n))
1694 .collect::<Result<Vec<_>>>()?;
1695
1696 Ok(leo_ast::Block { statements, span, id })
1697 }
1698
1699 fn let_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1701 debug_assert_eq!(node.kind(), LET_STMT);
1702 let span = self.to_span(node);
1703 let id = self.builder.next_id();
1704
1705 let place = match children(node).find(|n| matches!(n.kind(), IDENT_PATTERN | TUPLE_PATTERN | WILDCARD_PATTERN))
1707 {
1708 Some(pattern_node) => self.pattern_to_definition_place(&pattern_node)?,
1709 None => {
1710 self.emit_unexpected_str("pattern in let statement", node.text(), span);
1711 leo_ast::DefinitionPlace::Single(self.error_identifier(span))
1712 }
1713 };
1714
1715 let type_ = children(node).find(|n| n.kind().is_type()).map(|n| self.to_type(&n)).transpose()?;
1717
1718 let value = self.require_expression(node, "value in let statement")?;
1719
1720 Ok(leo_ast::DefinitionStatement { place, type_, value, span, id }.into())
1721 }
1722
1723 fn pattern_to_definition_place(&self, node: &SyntaxNode) -> Result<leo_ast::DefinitionPlace> {
1725 let span = self.to_span(node);
1726 match node.kind() {
1727 IDENT_PATTERN => {
1728 let ident = self.require_ident(node, "identifier in pattern");
1729 self.validate_definition_identifier(&ident);
1730 Ok(leo_ast::DefinitionPlace::Single(ident))
1731 }
1732 TUPLE_PATTERN => {
1733 let names = children(node)
1734 .filter(|n| matches!(n.kind(), IDENT_PATTERN | WILDCARD_PATTERN))
1735 .map(|n| {
1736 if n.kind() == WILDCARD_PATTERN {
1737 let span = self.to_span(&n);
1739 leo_ast::Identifier { name: Symbol::intern("_"), span, id: self.builder.next_id() }
1740 } else {
1741 let ident = self.require_ident(&n, "identifier in pattern");
1742 self.validate_definition_identifier(&ident);
1743 ident
1744 }
1745 })
1746 .collect();
1747 Ok(leo_ast::DefinitionPlace::Multiple(names))
1748 }
1749 WILDCARD_PATTERN => {
1750 let ident = leo_ast::Identifier { name: Symbol::intern("_"), span, id: self.builder.next_id() };
1751 Ok(leo_ast::DefinitionPlace::Single(ident))
1752 }
1753 _ => {
1754 self.emit_unexpected_str("valid pattern", node.text(), span);
1755 let ident = self.error_identifier(span);
1756 Ok(leo_ast::DefinitionPlace::Single(ident))
1757 }
1758 }
1759 }
1760
1761 fn const_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1763 debug_assert_eq!(node.kind(), CONST_STMT);
1764 let span = self.to_span(node);
1765 let id = self.builder.next_id();
1766
1767 let place = self.require_ident(node, "name in const declaration");
1768
1769 let type_ = self.require_type(node, "type in const declaration")?;
1770
1771 let value = self.require_expression(node, "value in const declaration")?;
1772
1773 Ok(leo_ast::ConstDeclaration { place, type_, value, span, id }.into())
1774 }
1775
1776 fn return_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1778 debug_assert_eq!(node.kind(), RETURN_STMT);
1779 let span = self.to_span(node);
1780 let id = self.builder.next_id();
1781
1782 let expression = children(node)
1784 .find(|n| n.kind().is_expression())
1785 .map(|n| self.to_expression(&n))
1786 .transpose()?
1787 .unwrap_or_else(|| leo_ast::UnitExpression { span, id: self.builder.next_id() }.into());
1788
1789 Ok(leo_ast::ReturnStatement { expression, span, id }.into())
1790 }
1791
1792 fn expr_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1794 debug_assert_eq!(node.kind(), EXPR_STMT);
1795 let span = self.to_span(node);
1796 let id = self.builder.next_id();
1797
1798 let expression = self.require_expression(node, "expression in expression statement")?;
1799
1800 Ok(leo_ast::ExpressionStatement { expression, span, id }.into())
1801 }
1802
1803 fn simple_assign_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1805 debug_assert_eq!(node.kind(), ASSIGN_STMT);
1806 let span = self.to_span(node);
1807 let id = self.builder.next_id();
1808
1809 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1810
1811 let place = match exprs.next() {
1812 Some(n) => self.to_expression(&n)?,
1813 None => {
1814 self.emit_unexpected_str("left side in assignment", node.text(), span);
1815 return Ok(leo_ast::ExpressionStatement { expression: self.error_expression(span), span, id }.into());
1816 }
1817 };
1818
1819 let value = match exprs.next() {
1820 Some(n) => self.to_expression(&n)?,
1821 None => {
1822 self.emit_unexpected_str("right side in assignment", node.text(), span);
1823 self.error_expression(span)
1824 }
1825 };
1826
1827 Ok(leo_ast::AssignStatement { place, value, span, id }.into())
1828 }
1829
1830 fn compound_assign_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1834 debug_assert_eq!(node.kind(), COMPOUND_ASSIGN_STMT);
1835 let span = self.to_span(node);
1836 let id = self.builder.next_id();
1837
1838 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1839
1840 let left = match exprs.next() {
1841 Some(n) => self.to_expression(&n)?,
1842 None => {
1843 self.emit_unexpected_str("left side in compound assignment", node.text(), span);
1844 return Ok(leo_ast::ExpressionStatement { expression: self.error_expression(span), span, id }.into());
1845 }
1846 };
1847
1848 let right = match exprs.next() {
1849 Some(n) => self.to_expression(&n)?,
1850 None => {
1851 self.emit_unexpected_str("right side in compound assignment", node.text(), span);
1852 self.error_expression(span)
1853 }
1854 };
1855
1856 let op_token =
1857 tokens(node).find(|t| is_assign_op(t.kind())).expect("COMPOUND_ASSIGN_STMT should have operator");
1858
1859 let binary_op = match op_token.kind() {
1860 PLUS_EQ => leo_ast::BinaryOperation::Add,
1861 MINUS_EQ => leo_ast::BinaryOperation::Sub,
1862 STAR_EQ => leo_ast::BinaryOperation::Mul,
1863 SLASH_EQ => leo_ast::BinaryOperation::Div,
1864 PERCENT_EQ => leo_ast::BinaryOperation::Rem,
1865 STAR2_EQ => leo_ast::BinaryOperation::Pow,
1866 AMP_EQ => leo_ast::BinaryOperation::BitwiseAnd,
1867 PIPE_EQ => leo_ast::BinaryOperation::BitwiseOr,
1868 CARET_EQ => leo_ast::BinaryOperation::Xor,
1869 SHL_EQ => leo_ast::BinaryOperation::Shl,
1870 SHR_EQ => leo_ast::BinaryOperation::Shr,
1871 AMP2_EQ => leo_ast::BinaryOperation::And,
1872 PIPE2_EQ => leo_ast::BinaryOperation::Or,
1873 k => panic!("unexpected compound assignment operator: {k:?}"),
1874 };
1875
1876 let value =
1877 leo_ast::BinaryExpression { left: left.clone(), right, op: binary_op, span, id: self.builder.next_id() }
1878 .into();
1879
1880 Ok(leo_ast::AssignStatement { place: left, value, span, id }.into())
1881 }
1882
1883 fn if_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1885 debug_assert_eq!(node.kind(), IF_STMT);
1886 let span = self.to_span(node);
1887 let id = self.builder.next_id();
1888
1889 let condition = self.require_expression(node, "condition in if statement")?;
1890
1891 let mut block_or_if = children(node).filter(|n| n.kind() == BLOCK || n.kind() == IF_STMT);
1894
1895 let then = match block_or_if.next() {
1896 Some(n) if n.kind() == BLOCK => self.to_block(&n)?,
1897 _ => {
1898 self.emit_unexpected_str("then block in if statement", node.text(), span);
1899 self.error_block(span)
1900 }
1901 };
1902
1903 let otherwise = block_or_if.next().map(|n| self.to_statement(&n)).transpose()?.map(Box::new);
1904
1905 Ok(leo_ast::ConditionalStatement { condition, then, otherwise, span, id }.into())
1906 }
1907
1908 fn for_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1910 debug_assert!(matches!(node.kind(), FOR_STMT | FOR_INCLUSIVE_STMT));
1911 let span = self.to_span(node);
1912 let id = self.builder.next_id();
1913
1914 let variable = self.require_ident(node, "variable in for statement");
1915
1916 let type_ = children(node).find(|n| n.kind().is_type()).map(|n| self.to_type(&n)).transpose()?;
1918
1919 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1921
1922 let start = match exprs.next() {
1923 Some(n) => self.to_expression(&n)?,
1924 None => {
1925 self.emit_unexpected_str("start expression in for statement", node.text(), span);
1926 self.error_expression(span)
1927 }
1928 };
1929
1930 let stop = match exprs.next() {
1931 Some(n) => self.to_expression(&n)?,
1932 None => {
1933 self.emit_unexpected_str("stop expression in for statement", node.text(), span);
1934 self.error_expression(span)
1935 }
1936 };
1937
1938 let block = match children(node).find(|n| n.kind() == BLOCK) {
1940 Some(block_node) => self.to_block(&block_node)?,
1941 None => {
1942 self.emit_unexpected_str("block in for statement", node.text(), span);
1943 self.error_block(span)
1944 }
1945 };
1946
1947 let inclusive = node.kind() == FOR_INCLUSIVE_STMT;
1948
1949 Ok(leo_ast::IterationStatement { variable, type_, start, stop, inclusive, block, span, id }.into())
1950 }
1951
1952 fn collect_program_item(
1958 &self,
1959 item: &SyntaxNode,
1960 is_in_program_block: bool,
1961 functions: &mut Vec<(Symbol, leo_ast::Function)>,
1962 composites: &mut Vec<(Symbol, leo_ast::Composite)>,
1963 consts: &mut Vec<(Symbol, leo_ast::ConstDeclaration)>,
1964 interfaces: &mut Vec<(Symbol, leo_ast::Interface)>,
1965 ) -> Result<()> {
1966 match item.kind() {
1967 FUNCTION_DEF | FINAL_FN_DEF | VIEW_FN_DEF => {
1968 if item.kind() == VIEW_FN_DEF && !is_in_program_block {
1969 let span = self.to_span(item);
1971 self.handler.emit_err(crate::errors::custom(
1972 "`view fn` is only allowed inside a `program { ... }` block.",
1973 span,
1974 ));
1975 }
1976 let func = self.to_function(item, is_in_program_block)?;
1977 functions.push((func.identifier.name, func));
1978 }
1979 STRUCT_DEF | RECORD_DEF => {
1980 let composite = self.to_composite(item)?;
1981 composites.push((composite.identifier.name, composite));
1982 }
1983 GLOBAL_CONST => {
1984 let global_const = self.to_global_const(item)?;
1985 consts.push((global_const.place.name, global_const));
1986 }
1987 INTERFACE_DEF => {
1988 let interface = self.to_interface(item)?;
1989 interfaces.push((interface.identifier.name, interface));
1990 }
1991 _ => {}
1992 }
1993 Ok(())
1994 }
1995
1996 fn collect_library_item(
1998 &self,
1999 item: &SyntaxNode,
2000 consts: &mut Vec<(Symbol, leo_ast::ConstDeclaration)>,
2001 structs: &mut Vec<(Symbol, leo_ast::Composite)>,
2002 functions: &mut Vec<(Symbol, leo_ast::Function)>,
2003 interfaces: &mut Vec<(Symbol, leo_ast::Interface)>,
2004 ) -> Result<()> {
2005 if is_library_item(item.kind()) {
2006 match item.kind() {
2007 GLOBAL_CONST => {
2008 let global_const = self.to_global_const(item)?;
2009 consts.push((global_const.place.name, global_const));
2010 }
2011 STRUCT_DEF => {
2012 let composite = self.to_composite(item)?;
2013 structs.push((composite.identifier.name, composite));
2014 }
2015 FUNCTION_DEF => {
2016 let func = self.to_function(item, false)?;
2018 functions.push((func.identifier.name, func));
2019 }
2020 INTERFACE_DEF => {
2021 let interface = self.to_interface(item)?;
2022 interfaces.push((interface.identifier.name, interface));
2023 }
2024 _ => {}
2025 }
2026 } else if item.kind() == VIEW_FN_DEF {
2027 let span = self.to_span(item);
2029 self.handler
2030 .emit_err(crate::errors::custom("`view fn` is only allowed inside a `program { ... }` block.", span));
2031 } else if is_program_item(item.kind()) {
2032 let span = self.to_span(item);
2034 self.handler.emit_err(crate::errors::custom(
2035 "Only `const` declarations, `struct` definitions, `fn` functions, and `interface` definitions are allowed in a library.",
2036 span,
2037 ));
2038 }
2039 Ok(())
2042 }
2043
2044 fn to_module(&self, node: &SyntaxNode, program_name: Symbol, path: Vec<Symbol>) -> Result<leo_ast::Module> {
2046 let mut functions = Vec::new();
2048 let mut composites = Vec::new();
2049 let mut consts = Vec::new();
2050 let mut interfaces = Vec::new();
2051
2052 for child in children(node) {
2053 if child.kind() == PROGRAM_DECL {
2054 for item in children(&child) {
2055 self.collect_program_item(
2056 &item,
2057 true,
2058 &mut functions,
2059 &mut composites,
2060 &mut consts,
2061 &mut interfaces,
2062 )?;
2063 }
2064 } else {
2065 self.collect_program_item(
2066 &child,
2067 false,
2068 &mut functions,
2069 &mut composites,
2070 &mut consts,
2071 &mut interfaces,
2072 )?;
2073 }
2074 }
2075
2076 functions.sort_by_key(|func| if func.1.variant.is_entry() { 0u8 } else { 1u8 });
2078
2079 Ok(leo_ast::Module { unit_name: program_name, path, consts, composites, functions, interfaces })
2080 }
2081
2082 fn to_main(&self, node: &SyntaxNode) -> Result<leo_ast::Program> {
2084 let mut imports = indexmap::IndexMap::new();
2086 let mut functions = Vec::new();
2087 let mut composites = Vec::new();
2088 let mut consts = Vec::new();
2089 let mut mappings = Vec::new();
2090 let mut storage_variables = Vec::new();
2091 let mut constructors = Vec::new();
2092 let mut interfaces = Vec::new();
2093 let mut program_name = None;
2094 let mut network = None;
2095 let mut parents = Vec::new();
2096 let mut span = None;
2097
2098 for child in children(node) {
2099 match child.kind() {
2100 IMPORT => {
2101 let program_id = self.import_to_program_id(&child)?;
2102 imports.insert(program_id.as_symbol(), program_id);
2103 }
2104 PROGRAM_DECL => {
2105 if program_name.is_some() {
2106 self.handler
2107 .emit_err(crate::errors::multiple_program_declarations(self.non_trivia_span(&child)));
2108 continue;
2109 }
2110 let (pname, pnetwork, pparents) = self.program_decl_to_name_with_parent(&child)?;
2112 program_name = Some(pname);
2113 network = Some(pnetwork);
2114 parents = pparents;
2115 span = Some(self.to_span(&child));
2116
2117 for item in children(&child) {
2119 self.collect_program_item(
2120 &item,
2121 true,
2122 &mut functions,
2123 &mut composites,
2124 &mut consts,
2125 &mut interfaces,
2126 )?;
2127 match item.kind() {
2128 MAPPING_DEF => {
2129 let mapping = self.to_mapping(&item)?;
2130 mappings.push((mapping.identifier.name, mapping));
2131 }
2132 STORAGE_DEF => {
2133 let storage = self.to_storage(&item)?;
2134 storage_variables.push((storage.identifier.name, storage));
2135 }
2136 CONSTRUCTOR_DEF => {
2137 constructors.push(self.to_constructor(&item)?);
2138 }
2139 _ => {}
2140 }
2141 }
2142 }
2143 _ => {
2144 self.collect_program_item(
2145 &child,
2146 false,
2147 &mut functions,
2148 &mut composites,
2149 &mut consts,
2150 &mut interfaces,
2151 )?;
2152 }
2153 }
2154 }
2155
2156 if let Some(extra) = constructors.get(1) {
2157 return Err(crate::errors::custom("A program can only have one constructor.", extra.span).into());
2158 }
2159
2160 let (Some(program_name), Some(network), Some(span)) = (program_name, network, span) else {
2161 return Err(crate::errors::missing_program_declaration(self.to_span(node)).into());
2162 };
2163
2164 functions.sort_by_key(|func| if func.1.variant.is_entry() { 0u8 } else { 1u8 });
2166
2167 let program_id = leo_ast::ProgramId { name: program_name, network };
2168 let program_id_as_symbol = program_id.as_symbol();
2169 let program_scope = leo_ast::ProgramScope {
2170 program_id,
2171 parents,
2172 consts,
2173 composites,
2174 mappings,
2175 storage_variables,
2176 functions,
2177 interfaces,
2178 constructor: constructors.pop(),
2179 span,
2180 };
2181
2182 Ok(leo_ast::Program {
2183 imports,
2184 modules: indexmap::IndexMap::new(),
2185 stubs: indexmap::IndexMap::new(),
2186 program_scopes: vec![(program_id_as_symbol, program_scope)].into_iter().collect(),
2187 })
2188 }
2189
2190 fn to_library(&self, name: Symbol, node: &SyntaxNode) -> Result<leo_ast::Library> {
2192 let mut consts = Vec::new();
2193 let mut structs = Vec::new();
2194 let mut functions = Vec::new();
2195 let mut interfaces = Vec::new();
2196
2197 for child in children(node) {
2198 self.collect_library_item(&child, &mut consts, &mut structs, &mut functions, &mut interfaces)?;
2199 }
2200
2201 Ok(leo_ast::Library {
2202 name,
2203 modules: indexmap::IndexMap::new(),
2204 consts,
2205 structs,
2206 functions,
2207 interfaces,
2208 stubs: indexmap::IndexMap::new(),
2209 })
2210 }
2211
2212 fn import_to_program_id(&self, node: &SyntaxNode) -> Result<leo_ast::ProgramId> {
2214 debug_assert_eq!(node.kind(), IMPORT);
2215 let span = self.to_span(node);
2216
2217 let program_name_text = match tokens(node).find(|t| t.kind() == IDENT) {
2219 Some(name_token) => name_token.text().to_string(),
2220 None => {
2221 self.emit_unexpected_str("import name", node.text(), span);
2222 "_error".to_string()
2223 }
2224 };
2225
2226 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 {
2230 name: leo_ast::Identifier { name: Symbol::intern(&program_name_text), span, id: self.builder.next_id() },
2231 network: leo_ast::Identifier {
2232 name: Symbol::intern("aleo"),
2233 span: network_span,
2234 id: self.builder.next_id(),
2235 },
2236 };
2237
2238 if tokens(node).all(|t| t.kind() != KW_ALEO)
2240 && let Some(net_token) = find_invalid_network(node)
2241 {
2242 self.handler.emit_err(crate::errors::invalid_network(self.token_span(&net_token)));
2243 }
2244
2245 Ok(program_id)
2246 }
2247
2248 fn program_decl_to_name(&self, node: &SyntaxNode) -> Result<(leo_ast::Identifier, leo_ast::Identifier)> {
2250 debug_assert_eq!(node.kind(), PROGRAM_DECL);
2251 let span = self.to_span(node);
2252
2253 let program_name = self.require_ident(node, "program name");
2255
2256 let network = match tokens(node).find(|t| t.kind() == KW_ALEO) {
2257 Some(aleo_token) => leo_ast::Identifier {
2258 name: Symbol::intern("aleo"),
2259 span: self.token_span(&aleo_token),
2260 id: self.builder.next_id(),
2261 },
2262 None => {
2263 if let Some(net_token) = find_invalid_network(node) {
2265 self.handler.emit_err(crate::errors::invalid_network(self.token_span(&net_token)));
2266 } else {
2267 self.emit_unexpected_str(".aleo network", node.text(), span);
2268 }
2269 leo_ast::Identifier { name: Symbol::intern("aleo"), span, id: self.builder.next_id() }
2270 }
2271 };
2272
2273 Ok((program_name, network))
2274 }
2275
2276 fn program_decl_to_name_with_parent(
2278 &self,
2279 node: &SyntaxNode,
2280 ) -> Result<(leo_ast::Identifier, leo_ast::Identifier, Parents)> {
2281 debug_assert_eq!(node.kind(), PROGRAM_DECL);
2282 let (program_name, network) = self.program_decl_to_name(node)?;
2283
2284 let parents = if let Some(parent_list) = children(node).find(|n| n.kind() == PARENT_LIST) {
2285 self.collect_parent_list(&parent_list)?
2286 } else {
2287 vec![]
2288 };
2289
2290 Ok((program_name, network, parents))
2291 }
2292
2293 fn collect_parent_list(&self, node: &SyntaxNode) -> Result<Parents> {
2294 debug_assert_eq!(node.kind(), PARENT_LIST);
2295 children(node)
2296 .filter(|n| n.kind().is_type())
2297 .map(|n| self.to_type(&n).map(|t| (self.to_span(&n), t)))
2298 .collect::<Result<Vec<_>>>()
2299 }
2300
2301 fn collect_annotations(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::Annotation>> {
2303 children(node).filter(|n| n.kind() == ANNOTATION).map(|n| self.to_annotation(&n)).collect()
2304 }
2305
2306 fn require_block(&self, node: &SyntaxNode, span: Span) -> Result<leo_ast::Block> {
2308 Ok(children(node)
2309 .find(|n| n.kind() == BLOCK)
2310 .map(|n| self.to_block(&n))
2311 .transpose()?
2312 .unwrap_or_else(|| self.error_block(span)))
2313 }
2314
2315 fn to_function(&self, node: &SyntaxNode, is_in_program_block: bool) -> Result<leo_ast::Function> {
2317 debug_assert!(matches!(node.kind(), FUNCTION_DEF | FINAL_FN_DEF | VIEW_FN_DEF | CONSTRUCTOR_DEF));
2318 let span = self.span_including_annotations(node, self.non_trivia_span(node));
2319 let id = self.builder.next_id();
2320
2321 let annotations = self.collect_annotations(node)?;
2322
2323 let variant = if is_in_program_block {
2329 match node.kind() {
2330 VIEW_FN_DEF => leo_ast::Variant::View,
2331 FINAL_FN_DEF => leo_ast::Variant::FinalFn,
2332 FUNCTION_DEF | CONSTRUCTOR_DEF => leo_ast::Variant::EntryPoint,
2333 kind => unreachable!("unexpected function node kind in program block: {kind:?}"),
2334 }
2335 } else {
2336 match node.kind() {
2337 FINAL_FN_DEF => leo_ast::Variant::FinalFn,
2338 FUNCTION_DEF | VIEW_FN_DEF => leo_ast::Variant::Fn,
2339 kind => unreachable!("unexpected function node kind outside program block: {kind:?}"),
2340 }
2341 };
2342
2343 let identifier = self.require_ident(node, "function name");
2344 self.validate_identifier(&identifier);
2345
2346 let const_parameters = self.extract_const_parameters(node)?;
2347
2348 let input = children(node)
2350 .find(|n| n.kind() == PARAM_LIST)
2351 .map(|n| self.param_list_to_inputs(&n))
2352 .transpose()?
2353 .unwrap_or_default();
2354
2355 let (output, output_type) = if let Some(return_type_node) = children(node).find(|n| n.kind() == RETURN_TYPE) {
2361 self.return_type_to_outputs(&return_type_node)?
2363 } else if let Some(type_node) = children(node).find(|n| n.kind().is_type()) {
2364 let type_ = self.to_type(&type_node)?;
2366 let (mode, mode_start) = self.return_mode_before(node, &type_node);
2368 let type_span = self.content_span(&type_node);
2369 let output_span = match mode_start {
2370 Some(start) => Span::new(start, type_span.hi),
2371 None => type_span,
2372 };
2373 let output =
2374 vec![leo_ast::Output { mode, type_: type_.clone(), span: output_span, id: self.builder.next_id() }];
2375 (output, type_)
2376 } else {
2377 (Vec::new(), leo_ast::Type::Unit)
2378 };
2379
2380 let block = self.require_block(node, span)?;
2381
2382 Ok(leo_ast::Function {
2383 annotations,
2384 variant,
2385 identifier,
2386 const_parameters,
2387 input,
2388 output,
2389 output_type,
2390 block,
2391 span,
2392 id,
2393 })
2394 }
2395
2396 fn return_mode_before(&self, parent: &SyntaxNode, type_node: &SyntaxNode) -> (leo_ast::Mode, Option<u32>) {
2402 let type_start = type_node.text_range().start();
2403 let mut mode = leo_ast::Mode::None;
2404 let mut mode_start = None;
2405 for token in tokens(parent) {
2406 let token_end = token.text_range().end();
2407 if token_end > type_start {
2408 break;
2409 }
2410 if let Some(m) = token_kind_to_mode(token.kind()) {
2411 mode = m;
2412 mode_start = Some(u32::from(token.text_range().start()) + self.start_pos);
2413 }
2414 }
2415 (mode, mode_start)
2416 }
2417
2418 fn return_type_to_outputs(&self, node: &SyntaxNode) -> Result<(Vec<leo_ast::Output>, leo_ast::Type)> {
2420 debug_assert_eq!(node.kind(), RETURN_TYPE);
2421
2422 let mut outputs = Vec::new();
2425 let mut current_mode = leo_ast::Mode::None;
2426 let mut current_mode_start: Option<u32> = None;
2427
2428 for child in node.children_with_tokens() {
2429 match &child {
2430 SyntaxElement::Token(token) if !token.kind().is_trivia() => {
2431 if let Some(m) = token_kind_to_mode(token.kind()) {
2432 current_mode = m;
2433 current_mode_start = Some(u32::from(token.text_range().start()) + self.start_pos);
2434 }
2435 }
2436 SyntaxElement::Node(child_node) if child_node.kind().is_type() => {
2437 let type_ = self.to_type(child_node)?;
2438 let type_span = self.content_span(child_node);
2439 let output_span = match current_mode_start.take() {
2440 Some(start) => Span::new(start, type_span.hi),
2441 None => type_span,
2442 };
2443 outputs.push(leo_ast::Output {
2444 mode: current_mode,
2445 type_,
2446 span: output_span,
2447 id: self.builder.next_id(),
2448 });
2449 current_mode = leo_ast::Mode::None;
2450 }
2451 _ => {}
2452 }
2453 }
2454
2455 let output_type = match outputs.len() {
2456 0 => leo_ast::Type::Unit,
2457 1 => outputs[0].type_.clone(),
2458 _ => leo_ast::TupleType::new(outputs.iter().map(|o| o.type_.clone()).collect()).into(),
2459 };
2460
2461 Ok((outputs, output_type))
2462 }
2463
2464 fn to_annotation(&self, node: &SyntaxNode) -> Result<leo_ast::Annotation> {
2466 debug_assert_eq!(node.kind(), ANNOTATION);
2467 let span = self.trimmed_span(node);
2468 let id = self.builder.next_id();
2469
2470 let identifier = match tokens(node).find(|t| t.kind() == IDENT || t.kind().is_keyword()) {
2473 Some(name_token) => {
2474 let name = Symbol::intern(name_token.text());
2475 let name_span = self.token_span(&name_token);
2476 leo_ast::Identifier { name, span: name_span, id: self.builder.next_id() }
2477 }
2478 None => {
2479 self.emit_unexpected_str("annotation name", node.text(), span);
2480 self.error_identifier(span)
2481 }
2482 };
2483
2484 let map = children(node)
2486 .filter(|n| n.kind() == ANNOTATION_PAIR)
2487 .filter_map(|pair| {
2488 let key =
2489 tokens(&pair).find(|t| t.kind() == IDENT || t.kind() == KW_ADDRESS || t.kind() == KW_MAPPING)?;
2490 let val = tokens(&pair).find(|t| t.kind() == STRING)?;
2491 let text = val.text();
2492 Some((Symbol::intern(key.text()), text[1..text.len() - 1].to_string()))
2493 })
2494 .collect();
2495
2496 Ok(leo_ast::Annotation { identifier, map, span, id })
2497 }
2498
2499 fn param_list_to_inputs(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::Input>> {
2501 debug_assert_eq!(node.kind(), PARAM_LIST);
2502
2503 children(node)
2504 .filter(|n| matches!(n.kind(), PARAM | PARAM_PUBLIC | PARAM_PRIVATE | PARAM_CONSTANT))
2505 .map(|n| self.param_to_input(&n))
2506 .collect()
2507 }
2508
2509 fn param_to_input(&self, node: &SyntaxNode) -> Result<leo_ast::Input> {
2511 debug_assert!(matches!(node.kind(), PARAM | PARAM_PUBLIC | PARAM_PRIVATE | PARAM_CONSTANT));
2512 let span = self.non_trivia_span(node);
2513 let id = self.builder.next_id();
2514
2515 let mode = node_kind_to_mode(node.kind());
2516
2517 let identifier = self.require_ident(node, "parameter name");
2518 self.validate_identifier(&identifier);
2519
2520 let type_ = self.require_type(node, "parameter type")?;
2521
2522 Ok(leo_ast::Input { identifier, mode, type_, span, id })
2523 }
2524
2525 fn to_const_parameters(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::ConstParameter>> {
2527 debug_assert_eq!(node.kind(), CONST_PARAM_LIST);
2528
2529 children(node)
2530 .filter(|n| n.kind() == CONST_PARAM)
2531 .map(|n| {
2532 let span = self.non_trivia_span(&n);
2533 let id = self.builder.next_id();
2534
2535 let identifier = self.require_ident(&n, "const parameter name");
2536
2537 let type_ = self.require_type(&n, "const parameter type")?;
2538
2539 Ok(leo_ast::ConstParameter { identifier, type_, span, id })
2540 })
2541 .collect()
2542 }
2543
2544 fn extract_const_parameters(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::ConstParameter>> {
2546 children(node)
2547 .find(|n| n.kind() == CONST_PARAM_LIST)
2548 .map(|n| self.to_const_parameters(&n))
2549 .transpose()
2550 .map(|opt| opt.unwrap_or_default())
2551 }
2552
2553 fn to_composite(&self, node: &SyntaxNode) -> Result<leo_ast::Composite> {
2555 debug_assert!(matches!(node.kind(), STRUCT_DEF | RECORD_DEF));
2556 let span = self.non_trivia_span(node);
2557 let id = self.builder.next_id();
2558
2559 let is_record = node.kind() == RECORD_DEF;
2560
2561 let identifier = self.require_ident(node, "struct/record name");
2562 self.validate_identifier(&identifier);
2563
2564 let const_parameters = self.extract_const_parameters(node)?;
2565
2566 let members = children(node)
2568 .filter(|n| {
2569 matches!(
2570 n.kind(),
2571 STRUCT_MEMBER | STRUCT_MEMBER_PUBLIC | STRUCT_MEMBER_PRIVATE | STRUCT_MEMBER_CONSTANT
2572 )
2573 })
2574 .map(|n| self.struct_member_to_member(&n))
2575 .collect::<Result<Vec<_>>>()?;
2576
2577 Ok(leo_ast::Composite { identifier, const_parameters, members, is_record, span, id })
2578 }
2579
2580 fn struct_member_to_member(&self, node: &SyntaxNode) -> Result<leo_ast::Member> {
2582 debug_assert!(matches!(
2583 node.kind(),
2584 STRUCT_MEMBER | STRUCT_MEMBER_PUBLIC | STRUCT_MEMBER_PRIVATE | STRUCT_MEMBER_CONSTANT
2585 ));
2586 let span = self.non_trivia_span(node);
2587 let id = self.builder.next_id();
2588
2589 let mode = node_kind_to_mode(node.kind());
2590
2591 let identifier = self.require_ident(node, "member name");
2592 self.validate_identifier(&identifier);
2593
2594 let type_ = self.require_type(node, "member type")?;
2595
2596 Ok(leo_ast::Member { mode, identifier, type_, span, id })
2597 }
2598
2599 fn to_global_const(&self, node: &SyntaxNode) -> Result<leo_ast::ConstDeclaration> {
2601 debug_assert_eq!(node.kind(), GLOBAL_CONST);
2602 let span = self.non_trivia_span(node);
2603 let id = self.builder.next_id();
2604
2605 let place = self.require_ident(node, "const name");
2606 self.validate_definition_identifier(&place);
2607
2608 let type_ = self.require_type(node, "const type")?;
2609
2610 let value = self.require_expression(node, "const value")?;
2611
2612 Ok(leo_ast::ConstDeclaration { place, type_, value, span, id })
2613 }
2614
2615 fn parse_mapping_def(
2617 &self,
2618 node: &SyntaxNode,
2619 ) -> Result<(leo_ast::Identifier, leo_ast::Type, leo_ast::Type, Span, NodeID)> {
2620 debug_assert_eq!(node.kind(), MAPPING_DEF);
2621 let span = self.non_trivia_span(node);
2622 let id = self.builder.next_id();
2623 let identifier = self.require_ident(node, "name in mapping");
2624 let mut type_nodes = children(node).filter(|n| n.kind().is_type());
2625 let key_type = match type_nodes.next() {
2626 Some(key_node) => self.to_type(&key_node)?,
2627 None => {
2628 self.emit_unexpected_str("key type in mapping", node.text(), span);
2629 leo_ast::Type::Err
2630 }
2631 };
2632 let value_type = match type_nodes.next() {
2633 Some(value_node) => self.to_type(&value_node)?,
2634 None => {
2635 self.emit_unexpected_str("value type in mapping", node.text(), span);
2636 leo_ast::Type::Err
2637 }
2638 };
2639 Ok((identifier, key_type, value_type, span, id))
2640 }
2641
2642 fn to_mapping(&self, node: &SyntaxNode) -> Result<leo_ast::Mapping> {
2644 let (identifier, key_type, value_type, span, id) = self.parse_mapping_def(node)?;
2645 Ok(leo_ast::Mapping { identifier, key_type, value_type, span, id })
2646 }
2647
2648 fn to_mapping_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::MappingPrototype> {
2650 let (identifier, key_type, value_type, span, id) = self.parse_mapping_def(node)?;
2651 Ok(leo_ast::MappingPrototype { identifier, key_type, value_type, span, id })
2652 }
2653
2654 fn parse_storage_def(&self, node: &SyntaxNode) -> Result<(leo_ast::Identifier, leo_ast::Type, Span, NodeID)> {
2656 debug_assert_eq!(node.kind(), STORAGE_DEF);
2657 let span = self.non_trivia_span(node);
2658 let id = self.builder.next_id();
2659 let identifier = self.require_ident(node, "name in storage");
2660 let type_ = self.require_type(node, "type in storage")?;
2661 Ok((identifier, type_, span, id))
2662 }
2663
2664 fn to_storage(&self, node: &SyntaxNode) -> Result<leo_ast::StorageVariable> {
2666 let (identifier, type_, span, id) = self.parse_storage_def(node)?;
2667 Ok(leo_ast::StorageVariable { identifier, type_, span, id })
2668 }
2669
2670 fn to_storage_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::StorageVariablePrototype> {
2672 let (identifier, type_, span, id) = self.parse_storage_def(node)?;
2673 Ok(leo_ast::StorageVariablePrototype { identifier, type_, span, id })
2674 }
2675
2676 fn to_constructor(&self, node: &SyntaxNode) -> Result<leo_ast::Constructor> {
2678 debug_assert_eq!(node.kind(), CONSTRUCTOR_DEF);
2679 let span = self.span_including_annotations(node, self.non_trivia_span(node));
2680 let id = self.builder.next_id();
2681
2682 let annotations = self.collect_annotations(node)?;
2683 let block = self.require_block(node, span)?;
2684
2685 Ok(leo_ast::Constructor { annotations, block, span, id })
2686 }
2687
2688 fn to_interface(&self, node: &SyntaxNode) -> Result<leo_ast::Interface> {
2694 debug_assert_eq!(node.kind(), INTERFACE_DEF);
2695 let span = self.to_span(node);
2696
2697 let identifier = self.require_ident(node, "interface name");
2699
2700 let parents = if let Some(parent_list) = children(node).find(|n| n.kind() == PARENT_LIST) {
2703 self.collect_parent_list(&parent_list)?
2704 } else {
2705 vec![]
2706 };
2707
2708 let mut functions = Vec::new();
2709 let mut records = Vec::new();
2710 let mut mappings = Vec::new();
2711 let mut storages = Vec::new();
2712
2713 for child in children(node) {
2714 match child.kind() {
2715 FN_PROTOTYPE_DEF => {
2716 let proto = self.to_function_prototype(&child)?;
2717 functions.push((proto.identifier.name, proto));
2718 }
2719 RECORD_PROTOTYPE_DEF => {
2720 let proto = self.to_record_prototype(&child)?;
2721 records.push((proto.identifier.name, proto));
2722 }
2723 MAPPING_DEF => {
2724 let mapping = self.to_mapping_prototype(&child)?;
2725 mappings.push(mapping);
2726 }
2727 STORAGE_DEF => {
2728 let storage = self.to_storage_prototype(&child)?;
2729 storages.push(storage);
2730 }
2731 _ => {}
2732 }
2733 }
2734
2735 Ok(leo_ast::Interface {
2736 identifier,
2737 parents,
2738 span,
2739 id: self.builder.next_id(),
2740 functions,
2741 records,
2742 mappings,
2743 storages,
2744 })
2745 }
2746
2747 fn to_function_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::FunctionPrototype> {
2749 debug_assert_eq!(node.kind(), FN_PROTOTYPE_DEF);
2750 let span = self.to_span(node);
2751
2752 let is_view = tokens(node).any(|t| t.kind() == KW_VIEW);
2753 let variant = if is_view { leo_ast::Variant::View } else { leo_ast::Variant::EntryPoint };
2754 let identifier = self.require_ident(node, "function name");
2755
2756 let const_parameters = self.extract_const_parameters(node)?;
2758
2759 let input = children(node)
2761 .find(|n| n.kind() == PARAM_LIST)
2762 .map(|n| self.param_list_to_inputs(&n))
2763 .transpose()?
2764 .unwrap_or_default();
2765
2766 let output = if let Some(return_type_node) = children(node).find(|n| n.kind() == RETURN_TYPE) {
2769 self.return_type_to_outputs(&return_type_node)?.0
2771 } else if let Some(type_node) = children(node).find(|n| n.kind().is_type()) {
2772 let type_ = self.to_type(&type_node)?;
2774 let (mode, mode_start) = self.return_mode_before(node, &type_node);
2776 let type_span = self.content_span(&type_node);
2777 let output_span = match mode_start {
2778 Some(start) => Span::new(start, type_span.hi),
2779 None => type_span,
2780 };
2781 vec![leo_ast::Output { mode, type_, span: output_span, id: self.builder.next_id() }]
2782 } else {
2783 Vec::new()
2784 };
2785
2786 Ok(leo_ast::FunctionPrototype::new(
2787 vec![], variant,
2789 identifier,
2790 const_parameters,
2791 input,
2792 output,
2793 span,
2794 self.builder.next_id(),
2795 ))
2796 }
2797
2798 fn to_record_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::RecordPrototype> {
2800 debug_assert_eq!(node.kind(), RECORD_PROTOTYPE_DEF);
2801
2802 let span = self.to_span(node);
2803 let identifier = self.require_ident(node, "record name");
2804 let members = children(node)
2805 .filter(|n| {
2806 matches!(
2807 n.kind(),
2808 STRUCT_MEMBER | STRUCT_MEMBER_PUBLIC | STRUCT_MEMBER_PRIVATE | STRUCT_MEMBER_CONSTANT
2809 )
2810 })
2811 .map(|n| self.struct_member_to_member(&n))
2812 .collect::<Result<Vec<_>>>()?;
2813
2814 let is_redundant = members.is_empty()
2816 || members.iter().all(|m| {
2817 m.identifier.name == sym::owner && m.type_ == leo_ast::Type::Address && m.mode == leo_ast::Mode::None
2818 });
2819 if is_redundant && !members.is_empty() {
2820 self.handler.emit_warning(crate::errors::record_prototype_redundant(identifier.name, span));
2822 return Ok(leo_ast::RecordPrototype { identifier, span, members: Vec::new(), id: self.builder.next_id() });
2823 } else if is_redundant {
2824 let had_braces = node.children_with_tokens().any(|c| c.kind() == L_BRACE);
2827 if had_braces {
2828 self.handler.emit_warning(crate::errors::record_prototype_redundant(identifier.name, span));
2829 }
2830 }
2831
2832 Ok(leo_ast::RecordPrototype { identifier, span, members, id: self.builder.next_id() })
2833 }
2834}
2835
2836fn clamped_span(range: TextRange, start_pos: u32, source_len: u32) -> Span {
2842 let end = start_pos + source_len;
2843 let lo = (u32::from(range.start()) + start_pos).min(end);
2844 let hi = (u32::from(range.end()) + start_pos).min(end).max(lo);
2845 Span::new(lo, hi)
2846}
2847
2848fn emit_lex_errors(handler: &Handler, lex_errors: &[leo_parser_rowan::LexError], start_pos: u32, source_len: u32) {
2850 use leo_parser_rowan::LexErrorKind;
2851 for error in lex_errors {
2852 let span = clamped_span(error.range, start_pos, source_len);
2853
2854 match &error.kind {
2855 LexErrorKind::InvalidDigit { digit, radix, token } => {
2856 handler.emit_err(crate::errors::wrong_digit_for_radix_span(*digit, *radix, token, span));
2857 }
2858 LexErrorKind::CouldNotLex { content } => {
2859 handler.emit_err(crate::errors::could_not_lex_span(content, span));
2860 }
2861 LexErrorKind::BidiOverride => {
2862 handler.emit_err(crate::errors::lexer_bidi_override_span(span));
2863 }
2864 }
2865 }
2866}
2867
2868fn emit_parse_errors(
2871 handler: &Handler,
2872 errors: &[leo_parser_rowan::ParseError],
2873 start_pos: u32,
2874 source_len: u32,
2875 lex_errors: &[leo_parser_rowan::LexError],
2876) {
2877 use std::collections::HashSet;
2878
2879 let has_lex_errors = !lex_errors.is_empty();
2880
2881 let lex_ranges: Vec<(u32, u32)> = lex_errors
2883 .iter()
2884 .map(|e| {
2885 let lo = u32::from(e.range.start()).saturating_add(start_pos);
2886 let hi = u32::from(e.range.end()).saturating_add(start_pos);
2887 (lo, hi)
2888 })
2889 .collect();
2890
2891 let mut emitted_ranges: HashSet<(u32, u32)> = HashSet::new();
2893 let mut count = 0;
2894 let max_errors = 10;
2895
2896 for error in errors {
2897 if count >= max_errors {
2898 break;
2899 }
2900
2901 let span = clamped_span(error.range, start_pos, source_len);
2902 let range_key = (span.lo, span.hi);
2903
2904 if emitted_ranges.contains(&range_key) {
2906 continue;
2907 }
2908
2909 if has_lex_errors && span.lo == span.hi && span.hi == start_pos + source_len {
2912 continue;
2913 }
2914
2915 if lex_ranges.iter().any(|&(lo, hi)| span.lo < hi && span.hi > lo) {
2918 continue;
2919 }
2920
2921 emitted_ranges.insert(range_key);
2922
2923 let is_eof_error = match &error.found {
2926 Some(f) => f.is_empty() || f == "end of file",
2927 None => false,
2928 } || (span.lo == span.hi && span.hi >= start_pos + source_len);
2929
2930 if is_eof_error {
2931 handler.emit_err(crate::errors::unexpected_eof(span));
2932 count += 1;
2933 continue;
2934 }
2935
2936 if let Some(found) = &error.found {
2938 if error.expected.is_empty() {
2939 handler.emit_err(crate::errors::custom(&error.message, span));
2942 } else {
2943 let expected_str = error.expected.join(", ");
2944 handler.emit_err(crate::errors::unexpected(found, expected_str, span));
2945 }
2946 count += 1;
2947 continue;
2948 }
2949
2950 handler.emit_err(crate::errors::custom(&error.message, span));
2952 count += 1;
2953 }
2954}
2955
2956fn conversion_context<'a>(
2958 handler: &'a Handler,
2959 node_builder: &'a NodeBuilder,
2960 lex_errors: &[leo_parser_rowan::LexError],
2961 parse_errors: &[leo_parser_rowan::ParseError],
2962 start_pos: u32,
2963 source_len: u32,
2964) -> ConversionContext<'a> {
2965 emit_lex_errors(handler, lex_errors, start_pos, source_len);
2966 emit_parse_errors(handler, parse_errors, start_pos, source_len, lex_errors);
2967 let has_errors = !parse_errors.is_empty() || !lex_errors.is_empty();
2968 ConversionContext::new(handler, node_builder, start_pos, has_errors)
2969}
2970
2971pub fn parse_expression(
2973 handler: Handler,
2974 node_builder: &NodeBuilder,
2975 source: &str,
2976 start_pos: u32,
2977 _network: NetworkName,
2978) -> Result<leo_ast::Expression> {
2979 let parse = leo_parser_rowan::parse_expression_entry(source);
2980 let ctx =
2981 conversion_context(&handler, node_builder, parse.lex_errors(), parse.errors(), start_pos, source.len() as u32);
2982 ctx.to_expression(&parse.syntax())
2983}
2984
2985pub fn parse_statement(
2987 handler: Handler,
2988 node_builder: &NodeBuilder,
2989 source: &str,
2990 start_pos: u32,
2991 _network: NetworkName,
2992) -> Result<leo_ast::Statement> {
2993 let parse = leo_parser_rowan::parse_statement_entry(source);
2994 let ctx =
2995 conversion_context(&handler, node_builder, parse.lex_errors(), parse.errors(), start_pos, source.len() as u32);
2996 ctx.to_statement(&parse.syntax())
2997}
2998
2999pub fn parse_module(
3001 handler: Handler,
3002 node_builder: &NodeBuilder,
3003 source: &str,
3004 start_pos: u32,
3005 program_name: Symbol,
3006 path: Vec<Symbol>,
3007 _network: NetworkName,
3008) -> Result<leo_ast::Module> {
3009 let parse = leo_parser_rowan::parse_module_entry(source);
3010 let ctx =
3011 conversion_context(&handler, node_builder, parse.lex_errors(), parse.errors(), start_pos, source.len() as u32);
3012 ctx.to_module(&parse.syntax(), program_name, path)
3013}
3014
3015pub fn parse_program(
3017 handler: Handler,
3018 node_builder: &NodeBuilder,
3019 source: &SourceFile,
3020 modules: &[std::rc::Rc<SourceFile>],
3021 _network: NetworkName,
3022) -> Result<leo_ast::Program> {
3023 let parse = leo_parser_rowan::parse_file(&source.src);
3025 let main_context = conversion_context(
3026 &handler,
3027 node_builder,
3028 parse.lex_errors(),
3029 parse.errors(),
3030 source.absolute_start,
3031 source.src.len() as u32,
3032 );
3033 let mut program = main_context.to_main(&parse.syntax())?;
3034 let program_name = *program.program_scopes.first().unwrap().0;
3035
3036 let root_dir = match &source.name {
3038 FileName::Real(path) => path.parent().map(|p| p.to_path_buf()),
3039 _ => None,
3040 };
3041
3042 for module in modules {
3043 let module_parse = leo_parser_rowan::parse_module_entry(&module.src);
3044 let module_context = conversion_context(
3045 &handler,
3046 node_builder,
3047 module_parse.lex_errors(),
3048 module_parse.errors(),
3049 module.absolute_start,
3050 module.src.len() as u32,
3051 );
3052
3053 if let Some(key) = compute_module_key(&module.name, root_dir.as_deref()) {
3054 for segment in &key {
3055 if symbol_is_keyword(*segment) {
3056 return Err(crate::errors::keyword_used_as_module_name(key.iter().format("::"), segment).into());
3057 }
3058 }
3059 let module_ast = module_context.to_module(&module_parse.syntax(), program_name, key.clone())?;
3060 program.modules.insert(key, module_ast);
3061 }
3062 }
3063
3064 Ok(program)
3065}
3066
3067pub fn parse_library(
3069 handler: Handler,
3070 node_builder: &NodeBuilder,
3071 library_name: Symbol,
3072 source: &SourceFile,
3073 modules: &[std::rc::Rc<SourceFile>],
3074 _network: NetworkName,
3075) -> Result<leo_ast::Library> {
3076 let parse = leo_parser_rowan::parse_file(&source.src);
3078 let main_context = conversion_context(
3079 &handler,
3080 node_builder,
3081 parse.lex_errors(),
3082 parse.errors(),
3083 source.absolute_start,
3084 source.src.len() as u32,
3085 );
3086
3087 let mut library = main_context.to_library(library_name, &parse.syntax())?;
3088
3089 let root_dir = match &source.name {
3091 FileName::Real(path) => path.parent().map(|p| p.to_path_buf()),
3092 _ => None,
3093 };
3094
3095 for module_sf in modules {
3097 let module_parse = leo_parser_rowan::parse_module_entry(&module_sf.src);
3098 let module_context = conversion_context(
3099 &handler,
3100 node_builder,
3101 module_parse.lex_errors(),
3102 module_parse.errors(),
3103 module_sf.absolute_start,
3104 module_sf.src.len() as u32,
3105 );
3106
3107 if let Some(key) = compute_module_key(&module_sf.name, root_dir.as_deref()) {
3108 for segment in &key {
3109 if symbol_is_keyword(*segment) {
3110 return Err(crate::errors::keyword_used_as_module_name(key.iter().format("::"), segment).into());
3111 }
3112 }
3113 let module_ast = module_context.to_module(&module_parse.syntax(), library_name, key.clone())?;
3116 library.modules.insert(key, module_ast);
3117 }
3118 }
3119
3120 Ok(library)
3121}
3122
3123fn children(node: &SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ {
3129 node.children().filter(|n| !n.kind().is_trivia())
3130}
3131
3132fn tokens(node: &SyntaxNode) -> impl Iterator<Item = SyntaxToken> + '_ {
3134 node.children_with_tokens().filter_map(|elem| elem.into_token()).filter(|t| !t.kind().is_trivia())
3135}
3136
3137fn find_name_after_dot(node: &SyntaxNode) -> Option<SyntaxToken> {
3139 let dot_end = tokens(node).find(|t| t.kind() == DOT)?.text_range().end();
3140 tokens(node).filter(|t| t.text_range().start() >= dot_end).find(|t| t.kind() == IDENT || t.kind().is_keyword())
3141}
3142
3143fn first_non_trivia_token(node: &SyntaxNode) -> Option<SyntaxToken> {
3145 node.children_with_tokens().find_map(|e| e.into_token().filter(|t| !t.kind().is_trivia()))
3146}
3147
3148fn last_non_trivia_token(node: &SyntaxNode) -> Option<SyntaxToken> {
3150 node.children_with_tokens().filter_map(|e| e.into_token().filter(|t| !t.kind().is_trivia())).last()
3151}
3152
3153fn find_invalid_network(node: &SyntaxNode) -> Option<SyntaxToken> {
3155 let mut saw_dot = false;
3156 tokens(node).find(|t| {
3157 if t.kind() == DOT {
3158 saw_dot = true;
3159 return false;
3160 }
3161 saw_dot && t.kind() == IDENT
3162 })
3163}
3164
3165fn token_kind_to_mode(kind: SyntaxKind) -> Option<leo_ast::Mode> {
3167 match kind {
3168 KW_PUBLIC => Some(leo_ast::Mode::Public),
3169 KW_PRIVATE => Some(leo_ast::Mode::Private),
3170 KW_CONSTANT => Some(leo_ast::Mode::Constant),
3171 _ => None,
3172 }
3173}
3174
3175fn node_kind_to_mode(kind: SyntaxKind) -> leo_ast::Mode {
3177 match kind {
3178 PARAM_PUBLIC | STRUCT_MEMBER_PUBLIC => leo_ast::Mode::Public,
3179 PARAM_PRIVATE | STRUCT_MEMBER_PRIVATE => leo_ast::Mode::Private,
3180 PARAM_CONSTANT | STRUCT_MEMBER_CONSTANT => leo_ast::Mode::Constant,
3181 _ => leo_ast::Mode::None,
3182 }
3183}
3184
3185fn keyword_to_path_symbol(kind: SyntaxKind) -> Option<Symbol> {
3187 match kind {
3188 KW_SELF => Some(sym::SelfLower),
3189 KW_BLOCK => Some(sym::block),
3190 KW_NETWORK => Some(sym::network),
3191 KW_FINAL_UPPER => Some(sym::Final),
3192 _ => None,
3193 }
3194}
3195
3196fn is_assign_op(kind: SyntaxKind) -> bool {
3198 matches!(
3199 kind,
3200 EQ | PLUS_EQ
3201 | MINUS_EQ
3202 | STAR_EQ
3203 | SLASH_EQ
3204 | PERCENT_EQ
3205 | STAR2_EQ
3206 | AMP_EQ
3207 | PIPE_EQ
3208 | CARET_EQ
3209 | SHL_EQ
3210 | SHR_EQ
3211 | AMP2_EQ
3212 | PIPE2_EQ
3213 )
3214}
3215
3216fn keyword_to_primitive_type(kind: SyntaxKind) -> Option<leo_ast::Type> {
3218 let ty = match kind {
3219 KW_ADDRESS => leo_ast::Type::Address,
3220 KW_BOOL => leo_ast::Type::Boolean,
3221 KW_FIELD => leo_ast::Type::Field,
3222 KW_GROUP => leo_ast::Type::Group,
3223 KW_SCALAR => leo_ast::Type::Scalar,
3224 KW_SIGNATURE => leo_ast::Type::Signature,
3225 KW_STRING => leo_ast::Type::String,
3226 KW_DYN => leo_ast::Type::DynRecord,
3227 KW_IDENTIFIER => leo_ast::Type::Identifier,
3228 KW_U8 => leo_ast::Type::Integer(leo_ast::IntegerType::U8),
3229 KW_U16 => leo_ast::Type::Integer(leo_ast::IntegerType::U16),
3230 KW_U32 => leo_ast::Type::Integer(leo_ast::IntegerType::U32),
3231 KW_U64 => leo_ast::Type::Integer(leo_ast::IntegerType::U64),
3232 KW_U128 => leo_ast::Type::Integer(leo_ast::IntegerType::U128),
3233 KW_I8 => leo_ast::Type::Integer(leo_ast::IntegerType::I8),
3234 KW_I16 => leo_ast::Type::Integer(leo_ast::IntegerType::I16),
3235 KW_I32 => leo_ast::Type::Integer(leo_ast::IntegerType::I32),
3236 KW_I64 => leo_ast::Type::Integer(leo_ast::IntegerType::I64),
3237 KW_I128 => leo_ast::Type::Integer(leo_ast::IntegerType::I128),
3238 _ => return None,
3239 };
3240 Some(ty)
3241}
3242
3243fn token_to_binary_op(kind: SyntaxKind) -> leo_ast::BinaryOperation {
3245 match kind {
3246 EQ2 => leo_ast::BinaryOperation::Eq,
3247 BANG_EQ => leo_ast::BinaryOperation::Neq,
3248 LT => leo_ast::BinaryOperation::Lt,
3249 LT_EQ => leo_ast::BinaryOperation::Lte,
3250 GT => leo_ast::BinaryOperation::Gt,
3251 GT_EQ => leo_ast::BinaryOperation::Gte,
3252 PLUS => leo_ast::BinaryOperation::Add,
3253 MINUS => leo_ast::BinaryOperation::Sub,
3254 STAR => leo_ast::BinaryOperation::Mul,
3255 SLASH => leo_ast::BinaryOperation::Div,
3256 PERCENT => leo_ast::BinaryOperation::Rem,
3257 PIPE2 => leo_ast::BinaryOperation::Or,
3258 AMP2 => leo_ast::BinaryOperation::And,
3259 PIPE => leo_ast::BinaryOperation::BitwiseOr,
3260 AMP => leo_ast::BinaryOperation::BitwiseAnd,
3261 STAR2 => leo_ast::BinaryOperation::Pow,
3262 SHL => leo_ast::BinaryOperation::Shl,
3263 SHR => leo_ast::BinaryOperation::Shr,
3264 CARET => leo_ast::BinaryOperation::Xor,
3265 _ => panic!("unexpected binary operator: {:?}", kind),
3266 }
3267}
3268
3269fn symbol_is_keyword(symbol: Symbol) -> bool {
3270 matches!(
3271 symbol,
3272 sym::address
3273 | sym::aleo
3274 | sym::As
3275 | sym::assert
3276 | sym::assert_eq
3277 | sym::assert_neq
3278 | sym::block
3279 | sym::bool
3280 | sym::Const
3281 | sym::constant
3282 | sym::constructor
3283 | sym::Else
3284 | sym::False
3285 | sym::field
3286 | sym::FnUpper
3287 | sym::Fn
3288 | sym::For
3289 | sym::Final
3290 | sym::group
3291 | sym::i8
3292 | sym::i16
3293 | sym::i32
3294 | sym::i64
3295 | sym::i128
3296 | sym::If
3297 | sym::import
3298 | sym::In
3299 | sym::inline
3300 | sym::Let
3301 | sym::leo
3302 | sym::mapping
3303 | sym::storage
3304 | sym::network
3305 | sym::private
3306 | sym::program
3307 | sym::public
3308 | sym::record
3309 | sym::Return
3310 | sym::scalar
3311 | sym::script
3312 | sym::SelfLower
3313 | sym::signature
3314 | sym::string
3315 | sym::Struct
3316 | sym::True
3317 | sym::u8
3318 | sym::u16
3319 | sym::u32
3320 | sym::u64
3321 | sym::u128
3322 )
3323}
3324
3325fn compute_module_key(name: &FileName, root_dir: Option<&std::path::Path>) -> Option<Vec<Symbol>> {
3327 let path = match name {
3328 FileName::Custom(name) => std::path::Path::new(name).to_path_buf(),
3329 FileName::Real(path) => {
3330 let root = root_dir?;
3331 path.strip_prefix(root).ok()?.to_path_buf()
3332 }
3333 };
3334
3335 let mut key: Vec<Symbol> =
3336 path.components().map(|comp| Symbol::intern(&comp.as_os_str().to_string_lossy())).collect();
3337
3338 if let Some(last) = path.file_name()
3339 && let Some(stem) = std::path::Path::new(last).file_stem()
3340 {
3341 key.pop();
3342 key.push(Symbol::intern(&stem.to_string_lossy()));
3343 }
3344
3345 Some(key)
3346}
3347
3348fn is_library_item(kind: SyntaxKind) -> bool {
3350 matches!(kind, GLOBAL_CONST | STRUCT_DEF | FUNCTION_DEF | INTERFACE_DEF)
3351}
3352
3353fn is_program_item(kind: SyntaxKind) -> bool {
3355 matches!(
3356 kind,
3357 GLOBAL_CONST
3358 | FUNCTION_DEF
3359 | FINAL_FN_DEF
3360 | VIEW_FN_DEF
3361 | STRUCT_DEF
3362 | RECORD_DEF
3363 | INTERFACE_DEF
3364 | MAPPING_DEF
3365 | STORAGE_DEF
3366 | CONSTRUCTOR_DEF
3367 | PROGRAM_DECL
3368 | IMPORT
3369 )
3370}