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 leo_parser_rowan::is_keyword(&text) {
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 base = children(node)
1355 .find(|n| n.kind() == STRUCT_BASE_UPDATE)
1356 .and_then(|n| children(&n).find(|c| c.kind().is_expression()))
1357 .map(|n| self.to_expression(&n).map(Box::new))
1358 .transpose()?;
1359 let (_type_parameters, const_arguments) = self.extract_const_arg_list(node)?;
1360 Ok(leo_ast::CompositeExpression { path, const_arguments, members, base, span, id }.into())
1361 }
1362
1363 fn struct_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1365 debug_assert_eq!(node.kind(), STRUCT_EXPR);
1366 let span = self.content_span(node);
1367 let id = self.builder.next_id();
1368 let path = self.struct_expr_to_path(node)?;
1369 self.composite_expression_from_path(node, path, span, id)
1370 }
1371
1372 fn struct_expr_to_path(&self, node: &SyntaxNode) -> Result<leo_ast::Path> {
1374 let fallback_span = self.content_span(node);
1375
1376 let mut path_components = Vec::new();
1378 for token in tokens(node) {
1379 if token.kind() == L_BRACE {
1380 break;
1381 }
1382 if token.kind() == IDENT {
1383 path_components.push(self.to_identifier(&token));
1384 }
1385 }
1386
1387 let path_span = match (path_components.first(), path_components.last()) {
1388 (Some(first), Some(last)) => Span::new(first.span.lo, last.span.hi),
1389 _ => fallback_span,
1390 };
1391
1392 let name = match path_components.pop() {
1393 Some(name) => name,
1394 None => {
1395 self.emit_unexpected_str("type name in struct expression", node.text(), fallback_span);
1396 self.error_identifier(fallback_span)
1397 }
1398 };
1399 Ok(leo_ast::Path::new(None, path_components, name, path_span, self.builder.next_id()))
1400 }
1401
1402 fn struct_locator_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1404 let span = self.content_span(node);
1405 let id = self.builder.next_id();
1406 let path = self.locator_tokens_to_path(node)?;
1407 self.composite_expression_from_path(node, path, span, id)
1408 }
1409
1410 fn path_locator_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1412 let path = self.locator_tokens_to_path(node)?;
1413 Ok(leo_ast::Expression::Path(path))
1414 }
1415
1416 fn locator_tokens_to_path(&self, node: &SyntaxNode) -> Result<leo_ast::Path> {
1423 let span = self.to_span(node);
1424 let all_idents: Vec<_> = tokens(node).filter(|t| t.kind() == IDENT).collect();
1425
1426 let program_ident = match all_idents.first() {
1428 Some(t) => self.to_identifier(t),
1429 None => {
1430 self.emit_unexpected_str("program name", node.text(), span);
1431 self.error_identifier(span)
1432 }
1433 };
1434
1435 let network_ident = leo_ast::Identifier {
1437 name: Symbol::intern("aleo"),
1438 span: tokens(node).find(|t| t.kind() == KW_ALEO).map(|t| self.token_span(&t)).unwrap_or(span),
1439 id: self.builder.next_id(),
1440 };
1441
1442 let program = leo_ast::ProgramId { name: program_ident, network: network_ident };
1444
1445 let (qualifier, name) = if all_idents.len() < 2 {
1449 self.emit_unexpected_str("identifier", node.text(), span);
1450 (Vec::new(), self.error_identifier(span))
1451 } else {
1452 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();
1454 (qualifier, name)
1455 };
1456
1457 let path_span = Span::new(program.name.span.lo, name.span.hi);
1458 Ok(leo_ast::Path::new(Some(program), qualifier, name, path_span, self.builder.next_id()))
1459 }
1460
1461 fn struct_field_init_to_member(&self, node: &SyntaxNode) -> Result<leo_ast::CompositeFieldInitializer> {
1463 debug_assert!(matches!(node.kind(), STRUCT_FIELD_INIT | STRUCT_FIELD_SHORTHAND));
1464 let span = self.content_span(node);
1465 let id = self.builder.next_id();
1466
1467 let Some(ident_token) = tokens(node).find(|t| t.kind() == IDENT) else {
1468 self.emit_unexpected_str("identifier in struct field", node.text(), span);
1469 return Ok(leo_ast::CompositeFieldInitializer {
1470 identifier: self.error_identifier(span),
1471 expression: None,
1472 span,
1473 id,
1474 });
1475 };
1476 let identifier = self.to_identifier(&ident_token);
1477
1478 let expression = if node.kind() == STRUCT_FIELD_INIT {
1479 children(node).find(|n| n.kind().is_expression()).map(|n| self.to_expression(&n)).transpose()?
1480 } else {
1481 None
1482 };
1483
1484 Ok(leo_ast::CompositeFieldInitializer { identifier, expression, span, id })
1485 }
1486
1487 fn program_ref_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1489 debug_assert_eq!(node.kind(), PROGRAM_REF_EXPR);
1490 let span = self.content_span(node);
1491 let id = self.builder.next_id();
1492 let text: String = tokens(node).map(|t| t.text().to_string()).collect();
1493 Ok(leo_ast::Literal::address(text, span, id).into())
1494 }
1495
1496 fn path_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1498 debug_assert_eq!(node.kind(), PATH_EXPR);
1499
1500 let path = self.path_expr_to_path(node)?;
1501 let span = self.trimmed_span(node);
1502 let id = self.builder.next_id();
1503
1504 if path.user_program().is_none()
1506 && path.qualifier().len() == 1
1507 && path.qualifier()[0].name == sym::group
1508 && path.identifier().name == sym::GEN
1509 {
1510 return Ok(self.intrinsic_expression(sym::_group_gen, Vec::new(), span));
1511 }
1512
1513 if path.user_program().is_none() && path.qualifier().is_empty() {
1516 let name_text = path.identifier().name.to_string();
1517 if name_text.starts_with("sign1") && name_text.parse::<Signature<TestnetV0>>().is_ok() {
1518 return Ok(leo_ast::Literal::signature(name_text, span, id).into());
1519 }
1520 if name_text.starts_with('_') {
1523 self.handler.emit_err(crate::errors::identifier_cannot_start_with_underscore(span));
1524 return Ok(self.error_expression(span));
1525 }
1526 }
1527
1528 Ok(leo_ast::Expression::Path(path))
1529 }
1530
1531 fn keyword_expr_to_path(&self, node: &SyntaxNode, name: Symbol) -> Result<leo_ast::Expression> {
1533 let span = self.trimmed_span(node);
1534 let ident = leo_ast::Identifier { name, span, id: self.builder.next_id() };
1535 let path = leo_ast::Path::new(None, Vec::new(), ident, span, self.builder.next_id());
1536 Ok(leo_ast::Expression::Path(path))
1537 }
1538
1539 fn final_expr_to_expression(&self, node: &SyntaxNode) -> Result<leo_ast::Expression> {
1541 debug_assert_eq!(node.kind(), FINAL_EXPR);
1542 let span = self.content_span(node);
1543 let id = self.builder.next_id();
1544
1545 if let Some(block_node) = children(node).find(|n| n.kind() == BLOCK) {
1547 let block = self.to_block(&block_node)?;
1548 Ok(leo_ast::AsyncExpression { block, span, id }.into())
1549 } else {
1550 self.emit_unexpected_str("block in final expression", node.text(), span);
1552 Ok(self.error_expression(span))
1553 }
1554 }
1555
1556 fn path_expr_to_path(&self, node: &SyntaxNode) -> Result<leo_ast::Path> {
1564 let span = self.trimmed_span(node);
1565
1566 let mut path_components = Vec::new();
1568 for token in tokens(node) {
1569 match token.kind() {
1570 IDENT => {
1571 let text = token.text();
1572 if text.contains("::") {
1576 let token_span = self.token_span(&token);
1577 let mut offset = token_span.lo;
1578 for (i, segment) in text.split("::").enumerate() {
1579 if i > 0 {
1580 offset += 2; }
1582 let seg_span = Span::new(offset, offset + segment.len() as u32);
1583 path_components.push(leo_ast::Identifier {
1584 name: Symbol::intern(segment),
1585 span: seg_span,
1586 id: self.builder.next_id(),
1587 });
1588 offset += segment.len() as u32;
1589 }
1590 } else {
1591 path_components.push(self.to_identifier(&token));
1592 }
1593 }
1594 kind => {
1595 if let Some(name) = keyword_to_path_symbol(kind) {
1596 path_components.push(leo_ast::Identifier {
1597 name,
1598 span: self.token_span(&token),
1599 id: self.builder.next_id(),
1600 });
1601 }
1602 }
1603 }
1604 }
1605
1606 let name = match path_components.pop() {
1607 Some(name) => name,
1608 None => {
1609 self.emit_unexpected_str("identifier in path", node.text(), span);
1610 self.error_identifier(span)
1611 }
1612 };
1613 Ok(leo_ast::Path::new(None, path_components, name, span, self.builder.next_id()))
1614 }
1615
1616 fn to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1622 let span = self.to_span(node);
1623 let id = self.builder.next_id();
1624
1625 let stmt = match node.kind() {
1626 LET_STMT => self.let_stmt_to_statement(node)?,
1627 CONST_STMT => self.const_stmt_to_statement(node)?,
1628 RETURN_STMT => self.return_stmt_to_statement(node)?,
1629 EXPR_STMT => self.expr_stmt_to_statement(node)?,
1630 ASSIGN_STMT => self.simple_assign_to_statement(node)?,
1631 COMPOUND_ASSIGN_STMT => self.compound_assign_to_statement(node)?,
1632 IF_STMT => self.if_stmt_to_statement(node)?,
1633 FOR_STMT | FOR_INCLUSIVE_STMT => self.for_stmt_to_statement(node)?,
1634 BLOCK => self.to_block(node)?.into(),
1635 ASSERT_STMT => {
1636 let expression = self.require_expression(node, "expression in assert")?;
1637 leo_ast::AssertStatement { variant: leo_ast::AssertVariant::Assert(expression), span, id }.into()
1638 }
1639 ASSERT_EQ_STMT => {
1640 self.assert_binary_to_statement(node, "assert_eq", span, id, leo_ast::AssertVariant::AssertEq)?
1641 }
1642 ASSERT_NEQ_STMT => {
1643 self.assert_binary_to_statement(node, "assert_neq", span, id, leo_ast::AssertVariant::AssertNeq)?
1644 }
1645 ROOT => {
1647 if let Some(inner) = children(node).find(|n| n.kind().is_statement()) {
1648 self.to_statement(&inner)?
1649 } else {
1650 leo_ast::ExpressionStatement { expression: self.error_expression(span), span, id }.into()
1652 }
1653 }
1654 ERROR => leo_ast::ExpressionStatement { expression: self.error_expression(span), span, id }.into(),
1657 kind => panic!("unexpected statement kind: {:?}", kind),
1658 };
1659
1660 Ok(stmt)
1661 }
1662
1663 fn assert_binary_to_statement(
1665 &self,
1666 node: &SyntaxNode,
1667 label: &str,
1668 span: Span,
1669 id: leo_ast::NodeID,
1670 make_variant: fn(leo_ast::Expression, leo_ast::Expression) -> leo_ast::AssertVariant,
1671 ) -> Result<leo_ast::Statement> {
1672 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1673 let e0 = match exprs.next() {
1674 Some(expr) => self.to_expression(&expr)?,
1675 None => {
1676 self.emit_unexpected_str(&format!("first expression in {label}"), node.text(), span);
1677 self.error_expression(span)
1678 }
1679 };
1680 let e1 = match exprs.next() {
1681 Some(expr) => self.to_expression(&expr)?,
1682 None => {
1683 self.emit_unexpected_str(&format!("second expression in {label}"), node.text(), span);
1684 self.error_expression(span)
1685 }
1686 };
1687 Ok(leo_ast::AssertStatement { variant: make_variant(e0, e1), span, id }.into())
1688 }
1689
1690 fn to_block(&self, node: &SyntaxNode) -> Result<leo_ast::Block> {
1692 debug_assert_eq!(node.kind(), BLOCK);
1693 let span = self.to_span(node);
1694 let id = self.builder.next_id();
1695
1696 let statements = children(node)
1697 .filter(|n| n.kind().is_statement())
1698 .map(|n| self.to_statement(&n))
1699 .collect::<Result<Vec<_>>>()?;
1700
1701 Ok(leo_ast::Block { statements, span, id })
1702 }
1703
1704 fn let_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1706 debug_assert_eq!(node.kind(), LET_STMT);
1707 let span = self.to_span(node);
1708 let id = self.builder.next_id();
1709
1710 let place = match children(node).find(|n| matches!(n.kind(), IDENT_PATTERN | TUPLE_PATTERN | WILDCARD_PATTERN))
1712 {
1713 Some(pattern_node) => self.pattern_to_definition_place(&pattern_node)?,
1714 None => {
1715 self.emit_unexpected_str("pattern in let statement", node.text(), span);
1716 leo_ast::DefinitionPlace::Single(self.error_identifier(span))
1717 }
1718 };
1719
1720 let type_ = children(node).find(|n| n.kind().is_type()).map(|n| self.to_type(&n)).transpose()?;
1722
1723 let value = self.require_expression(node, "value in let statement")?;
1724
1725 Ok(leo_ast::DefinitionStatement { place, type_, value, span, id }.into())
1726 }
1727
1728 fn pattern_to_definition_place(&self, node: &SyntaxNode) -> Result<leo_ast::DefinitionPlace> {
1730 let span = self.to_span(node);
1731 match node.kind() {
1732 IDENT_PATTERN => {
1733 let ident = self.require_ident(node, "identifier in pattern");
1734 self.validate_definition_identifier(&ident);
1735 Ok(leo_ast::DefinitionPlace::Single(ident))
1736 }
1737 TUPLE_PATTERN => {
1738 let names = children(node)
1739 .filter(|n| matches!(n.kind(), IDENT_PATTERN | WILDCARD_PATTERN))
1740 .map(|n| {
1741 if n.kind() == WILDCARD_PATTERN {
1742 let span = self.to_span(&n);
1744 leo_ast::Identifier { name: Symbol::intern("_"), span, id: self.builder.next_id() }
1745 } else {
1746 let ident = self.require_ident(&n, "identifier in pattern");
1747 self.validate_definition_identifier(&ident);
1748 ident
1749 }
1750 })
1751 .collect();
1752 Ok(leo_ast::DefinitionPlace::Multiple(names))
1753 }
1754 WILDCARD_PATTERN => {
1755 let ident = leo_ast::Identifier { name: Symbol::intern("_"), span, id: self.builder.next_id() };
1756 Ok(leo_ast::DefinitionPlace::Single(ident))
1757 }
1758 _ => {
1759 self.emit_unexpected_str("valid pattern", node.text(), span);
1760 let ident = self.error_identifier(span);
1761 Ok(leo_ast::DefinitionPlace::Single(ident))
1762 }
1763 }
1764 }
1765
1766 fn const_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1768 debug_assert_eq!(node.kind(), CONST_STMT);
1769 let span = self.to_span(node);
1770 let id = self.builder.next_id();
1771
1772 let place = self.require_ident(node, "name in const declaration");
1773
1774 let type_ = self.require_type(node, "type in const declaration")?;
1775
1776 let value = self.require_expression(node, "value in const declaration")?;
1777
1778 Ok(leo_ast::ConstDeclaration { place, type_, value, span, id }.into())
1779 }
1780
1781 fn return_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1783 debug_assert_eq!(node.kind(), RETURN_STMT);
1784 let span = self.to_span(node);
1785 let id = self.builder.next_id();
1786
1787 let expression = children(node)
1789 .find(|n| n.kind().is_expression())
1790 .map(|n| self.to_expression(&n))
1791 .transpose()?
1792 .unwrap_or_else(|| leo_ast::UnitExpression { span, id: self.builder.next_id() }.into());
1793
1794 Ok(leo_ast::ReturnStatement { expression, span, id }.into())
1795 }
1796
1797 fn expr_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1799 debug_assert_eq!(node.kind(), EXPR_STMT);
1800 let span = self.to_span(node);
1801 let id = self.builder.next_id();
1802
1803 let expression = self.require_expression(node, "expression in expression statement")?;
1804
1805 Ok(leo_ast::ExpressionStatement { expression, span, id }.into())
1806 }
1807
1808 fn simple_assign_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1810 debug_assert_eq!(node.kind(), ASSIGN_STMT);
1811 let span = self.to_span(node);
1812 let id = self.builder.next_id();
1813
1814 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1815
1816 let place = match exprs.next() {
1817 Some(n) => self.to_expression(&n)?,
1818 None => {
1819 self.emit_unexpected_str("left side in assignment", node.text(), span);
1820 return Ok(leo_ast::ExpressionStatement { expression: self.error_expression(span), span, id }.into());
1821 }
1822 };
1823
1824 let value = match exprs.next() {
1825 Some(n) => self.to_expression(&n)?,
1826 None => {
1827 self.emit_unexpected_str("right side in assignment", node.text(), span);
1828 self.error_expression(span)
1829 }
1830 };
1831
1832 Ok(leo_ast::AssignStatement { place, value, span, id }.into())
1833 }
1834
1835 fn compound_assign_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1839 debug_assert_eq!(node.kind(), COMPOUND_ASSIGN_STMT);
1840 let span = self.to_span(node);
1841 let id = self.builder.next_id();
1842
1843 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1844
1845 let left = match exprs.next() {
1846 Some(n) => self.to_expression(&n)?,
1847 None => {
1848 self.emit_unexpected_str("left side in compound assignment", node.text(), span);
1849 return Ok(leo_ast::ExpressionStatement { expression: self.error_expression(span), span, id }.into());
1850 }
1851 };
1852
1853 let right = match exprs.next() {
1854 Some(n) => self.to_expression(&n)?,
1855 None => {
1856 self.emit_unexpected_str("right side in compound assignment", node.text(), span);
1857 self.error_expression(span)
1858 }
1859 };
1860
1861 let op_token =
1862 tokens(node).find(|t| is_assign_op(t.kind())).expect("COMPOUND_ASSIGN_STMT should have operator");
1863
1864 let binary_op = match op_token.kind() {
1865 PLUS_EQ => leo_ast::BinaryOperation::Add,
1866 MINUS_EQ => leo_ast::BinaryOperation::Sub,
1867 STAR_EQ => leo_ast::BinaryOperation::Mul,
1868 SLASH_EQ => leo_ast::BinaryOperation::Div,
1869 PERCENT_EQ => leo_ast::BinaryOperation::Rem,
1870 STAR2_EQ => leo_ast::BinaryOperation::Pow,
1871 AMP_EQ => leo_ast::BinaryOperation::BitwiseAnd,
1872 PIPE_EQ => leo_ast::BinaryOperation::BitwiseOr,
1873 CARET_EQ => leo_ast::BinaryOperation::Xor,
1874 SHL_EQ => leo_ast::BinaryOperation::Shl,
1875 SHR_EQ => leo_ast::BinaryOperation::Shr,
1876 AMP2_EQ => leo_ast::BinaryOperation::And,
1877 PIPE2_EQ => leo_ast::BinaryOperation::Or,
1878 k => panic!("unexpected compound assignment operator: {k:?}"),
1879 };
1880
1881 let value =
1882 leo_ast::BinaryExpression { left: left.clone(), right, op: binary_op, span, id: self.builder.next_id() }
1883 .into();
1884
1885 Ok(leo_ast::AssignStatement { place: left, value, span, id }.into())
1886 }
1887
1888 fn if_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1890 debug_assert_eq!(node.kind(), IF_STMT);
1891 let span = self.to_span(node);
1892 let id = self.builder.next_id();
1893
1894 let condition = self.require_expression(node, "condition in if statement")?;
1895
1896 let mut block_or_if = children(node).filter(|n| n.kind() == BLOCK || n.kind() == IF_STMT);
1899
1900 let then = match block_or_if.next() {
1901 Some(n) if n.kind() == BLOCK => self.to_block(&n)?,
1902 _ => {
1903 self.emit_unexpected_str("then block in if statement", node.text(), span);
1904 self.error_block(span)
1905 }
1906 };
1907
1908 let otherwise = block_or_if.next().map(|n| self.to_statement(&n)).transpose()?.map(Box::new);
1909
1910 Ok(leo_ast::ConditionalStatement { condition, then, otherwise, span, id }.into())
1911 }
1912
1913 fn for_stmt_to_statement(&self, node: &SyntaxNode) -> Result<leo_ast::Statement> {
1915 debug_assert!(matches!(node.kind(), FOR_STMT | FOR_INCLUSIVE_STMT));
1916 let span = self.to_span(node);
1917 let id = self.builder.next_id();
1918
1919 let variable = self.require_ident(node, "variable in for statement");
1920
1921 let type_ = children(node).find(|n| n.kind().is_type()).map(|n| self.to_type(&n)).transpose()?;
1923
1924 let mut exprs = children(node).filter(|n| n.kind().is_expression());
1926
1927 let start = match exprs.next() {
1928 Some(n) => self.to_expression(&n)?,
1929 None => {
1930 self.emit_unexpected_str("start expression in for statement", node.text(), span);
1931 self.error_expression(span)
1932 }
1933 };
1934
1935 let stop = match exprs.next() {
1936 Some(n) => self.to_expression(&n)?,
1937 None => {
1938 self.emit_unexpected_str("stop expression in for statement", node.text(), span);
1939 self.error_expression(span)
1940 }
1941 };
1942
1943 let block = match children(node).find(|n| n.kind() == BLOCK) {
1945 Some(block_node) => self.to_block(&block_node)?,
1946 None => {
1947 self.emit_unexpected_str("block in for statement", node.text(), span);
1948 self.error_block(span)
1949 }
1950 };
1951
1952 let inclusive = node.kind() == FOR_INCLUSIVE_STMT;
1953
1954 Ok(leo_ast::IterationStatement { variable, type_, start, stop, inclusive, block, span, id }.into())
1955 }
1956
1957 fn collect_program_item(
1963 &self,
1964 item: &SyntaxNode,
1965 is_in_program_block: bool,
1966 functions: &mut Vec<(Symbol, leo_ast::Function)>,
1967 composites: &mut Vec<(Symbol, leo_ast::Composite)>,
1968 consts: &mut Vec<(Symbol, leo_ast::ConstDeclaration)>,
1969 interfaces: &mut Vec<(Symbol, leo_ast::Interface)>,
1970 ) -> Result<()> {
1971 match item.kind() {
1972 FUNCTION_DEF | FINAL_FN_DEF | VIEW_FN_DEF => {
1973 if item.kind() == VIEW_FN_DEF && !is_in_program_block {
1974 let span = self.to_span(item);
1976 self.handler.emit_err(crate::errors::custom(
1977 "`view fn` is only allowed inside a `program { ... }` block.",
1978 span,
1979 ));
1980 }
1981 let func = self.to_function(item, is_in_program_block)?;
1982 functions.push((func.identifier.name, func));
1983 }
1984 STRUCT_DEF | RECORD_DEF => {
1985 if item.kind() == STRUCT_DEF && is_in_program_block {
1986 let span = self.non_trivia_span(item);
1987 self.handler.emit_err(
1988 crate::errors::custom(
1989 "`struct` definitions are not allowed inside a `program { ... }` block.",
1990 span,
1991 )
1992 .with_help("Move the declaration outside the `program` block, to the top level of the file."),
1993 );
1994 }
1995 let composite = self.to_composite(item)?;
1996 composites.push((composite.identifier.name, composite));
1997 }
1998 GLOBAL_CONST => {
1999 if is_in_program_block {
2000 let span = self.non_trivia_span(item);
2001 self.handler.emit_err(
2002 crate::errors::custom(
2003 "`const` declarations are not allowed inside a `program { ... }` block.",
2004 span,
2005 )
2006 .with_help("Move the declaration outside the `program` block, to the top level of the file."),
2007 );
2008 }
2009 let global_const = self.to_global_const(item)?;
2010 consts.push((global_const.place.name, global_const));
2011 }
2012 INTERFACE_DEF => {
2013 if is_in_program_block {
2014 let span = self.non_trivia_span(item);
2015 self.handler.emit_err(
2016 crate::errors::custom(
2017 "`interface` definitions are not allowed inside a `program { ... }` block.",
2018 span,
2019 )
2020 .with_help("Move the declaration outside the `program` block, to the top level of the file."),
2021 );
2022 }
2023 let interface = self.to_interface(item)?;
2024 interfaces.push((interface.identifier.name, interface));
2025 }
2026 _ => {}
2027 }
2028 Ok(())
2029 }
2030
2031 fn collect_library_item(
2033 &self,
2034 item: &SyntaxNode,
2035 consts: &mut Vec<(Symbol, leo_ast::ConstDeclaration)>,
2036 structs: &mut Vec<(Symbol, leo_ast::Composite)>,
2037 functions: &mut Vec<(Symbol, leo_ast::Function)>,
2038 interfaces: &mut Vec<(Symbol, leo_ast::Interface)>,
2039 ) -> Result<()> {
2040 if is_library_item(item.kind()) {
2041 match item.kind() {
2042 GLOBAL_CONST => {
2043 let global_const = self.to_global_const(item)?;
2044 consts.push((global_const.place.name, global_const));
2045 }
2046 STRUCT_DEF => {
2047 let composite = self.to_composite(item)?;
2048 structs.push((composite.identifier.name, composite));
2049 }
2050 FUNCTION_DEF => {
2051 let func = self.to_function(item, false)?;
2053 functions.push((func.identifier.name, func));
2054 }
2055 INTERFACE_DEF => {
2056 let interface = self.to_interface(item)?;
2057 interfaces.push((interface.identifier.name, interface));
2058 }
2059 _ => {}
2060 }
2061 } else if item.kind() == VIEW_FN_DEF {
2062 let span = self.to_span(item);
2064 self.handler
2065 .emit_err(crate::errors::custom("`view fn` is only allowed inside a `program { ... }` block.", span));
2066 } else if is_program_item(item.kind()) {
2067 let span = self.to_span(item);
2069 self.handler.emit_err(crate::errors::custom(
2070 "Only `const` declarations, `struct` definitions, `fn` functions, and `interface` definitions are allowed in a library.",
2071 span,
2072 ));
2073 }
2074 Ok(())
2077 }
2078
2079 fn to_module(&self, node: &SyntaxNode, program_name: Symbol, path: Vec<Symbol>) -> Result<leo_ast::Module> {
2081 let mut functions = Vec::new();
2083 let mut composites = Vec::new();
2084 let mut consts = Vec::new();
2085 let mut interfaces = Vec::new();
2086
2087 for child in children(node) {
2088 if child.kind() == PROGRAM_DECL {
2089 for item in children(&child) {
2090 self.collect_program_item(
2091 &item,
2092 true,
2093 &mut functions,
2094 &mut composites,
2095 &mut consts,
2096 &mut interfaces,
2097 )?;
2098 }
2099 } else {
2100 self.collect_program_item(
2101 &child,
2102 false,
2103 &mut functions,
2104 &mut composites,
2105 &mut consts,
2106 &mut interfaces,
2107 )?;
2108 }
2109 }
2110
2111 functions.sort_by_key(|func| if func.1.variant.is_entry() { 0u8 } else { 1u8 });
2113
2114 Ok(leo_ast::Module { unit_name: program_name, path, consts, composites, functions, interfaces })
2115 }
2116
2117 fn to_main(&self, node: &SyntaxNode) -> Result<leo_ast::Program> {
2119 let mut imports = indexmap::IndexMap::new();
2121 let mut functions = Vec::new();
2122 let mut composites = Vec::new();
2123 let mut consts = Vec::new();
2124 let mut mappings = Vec::new();
2125 let mut storage_variables = Vec::new();
2126 let mut constructors = Vec::new();
2127 let mut interfaces = Vec::new();
2128 let mut program_name = None;
2129 let mut network = None;
2130 let mut parents = Vec::new();
2131 let mut span = None;
2132
2133 for child in children(node) {
2134 match child.kind() {
2135 IMPORT => {
2136 let program_id = self.import_to_program_id(&child)?;
2137 imports.insert(program_id.as_symbol(), program_id);
2138 }
2139 PROGRAM_DECL => {
2140 if program_name.is_some() {
2141 self.handler
2142 .emit_err(crate::errors::multiple_program_declarations(self.non_trivia_span(&child)));
2143 continue;
2144 }
2145 let (pname, pnetwork, pparents) = self.program_decl_to_name_with_parent(&child)?;
2147 program_name = Some(pname);
2148 network = Some(pnetwork);
2149 parents = pparents;
2150 span = Some(self.to_span(&child));
2151
2152 for item in children(&child) {
2154 self.collect_program_item(
2155 &item,
2156 true,
2157 &mut functions,
2158 &mut composites,
2159 &mut consts,
2160 &mut interfaces,
2161 )?;
2162 match item.kind() {
2163 MAPPING_DEF => {
2164 let mapping = self.to_mapping(&item)?;
2165 mappings.push((mapping.identifier.name, mapping));
2166 }
2167 STORAGE_DEF => {
2168 let storage = self.to_storage(&item)?;
2169 storage_variables.push((storage.identifier.name, storage));
2170 }
2171 CONSTRUCTOR_DEF => {
2172 constructors.push(self.to_constructor(&item)?);
2173 }
2174 _ => {}
2175 }
2176 }
2177 }
2178 _ => {
2179 self.collect_program_item(
2180 &child,
2181 false,
2182 &mut functions,
2183 &mut composites,
2184 &mut consts,
2185 &mut interfaces,
2186 )?;
2187 }
2188 }
2189 }
2190
2191 if let Some(extra) = constructors.get(1) {
2192 return Err(crate::errors::custom("A program can only have one constructor.", extra.span).into());
2193 }
2194
2195 let (Some(program_name), Some(network), Some(span)) = (program_name, network, span) else {
2196 return Err(crate::errors::missing_program_declaration(self.to_span(node)).into());
2197 };
2198
2199 functions.sort_by_key(|func| if func.1.variant.is_entry() { 0u8 } else { 1u8 });
2201
2202 let program_id = leo_ast::ProgramId { name: program_name, network };
2203 let program_id_as_symbol = program_id.as_symbol();
2204 let program_scope = leo_ast::ProgramScope {
2205 program_id,
2206 parents,
2207 consts,
2208 composites,
2209 mappings,
2210 storage_variables,
2211 functions,
2212 interfaces,
2213 constructor: constructors.pop(),
2214 span,
2215 };
2216
2217 Ok(leo_ast::Program {
2218 imports,
2219 modules: indexmap::IndexMap::new(),
2220 stubs: indexmap::IndexMap::new(),
2221 program_scopes: vec![(program_id_as_symbol, program_scope)].into_iter().collect(),
2222 })
2223 }
2224
2225 fn to_library(&self, name: Symbol, node: &SyntaxNode) -> Result<leo_ast::Library> {
2227 let mut consts = Vec::new();
2228 let mut structs = Vec::new();
2229 let mut functions = Vec::new();
2230 let mut interfaces = Vec::new();
2231
2232 for child in children(node) {
2233 self.collect_library_item(&child, &mut consts, &mut structs, &mut functions, &mut interfaces)?;
2234 }
2235
2236 Ok(leo_ast::Library {
2237 name,
2238 modules: indexmap::IndexMap::new(),
2239 consts,
2240 structs,
2241 functions,
2242 interfaces,
2243 stubs: indexmap::IndexMap::new(),
2244 })
2245 }
2246
2247 fn import_to_program_id(&self, node: &SyntaxNode) -> Result<leo_ast::ProgramId> {
2249 debug_assert_eq!(node.kind(), IMPORT);
2250 let span = self.to_span(node);
2251
2252 let program_name_text = match tokens(node).find(|t| t.kind() == IDENT) {
2254 Some(name_token) => name_token.text().to_string(),
2255 None => {
2256 self.emit_unexpected_str("import name", node.text(), span);
2257 "_error".to_string()
2258 }
2259 };
2260
2261 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 {
2265 name: leo_ast::Identifier { name: Symbol::intern(&program_name_text), span, id: self.builder.next_id() },
2266 network: leo_ast::Identifier {
2267 name: Symbol::intern("aleo"),
2268 span: network_span,
2269 id: self.builder.next_id(),
2270 },
2271 };
2272
2273 if tokens(node).all(|t| t.kind() != KW_ALEO)
2275 && let Some(net_token) = find_invalid_network(node)
2276 {
2277 self.handler.emit_err(crate::errors::invalid_network(self.token_span(&net_token)));
2278 }
2279
2280 Ok(program_id)
2281 }
2282
2283 fn program_decl_to_name(&self, node: &SyntaxNode) -> Result<(leo_ast::Identifier, leo_ast::Identifier)> {
2285 debug_assert_eq!(node.kind(), PROGRAM_DECL);
2286 let span = self.to_span(node);
2287
2288 let program_name = self.require_ident(node, "program name");
2290
2291 let network = match tokens(node).find(|t| t.kind() == KW_ALEO) {
2292 Some(aleo_token) => leo_ast::Identifier {
2293 name: Symbol::intern("aleo"),
2294 span: self.token_span(&aleo_token),
2295 id: self.builder.next_id(),
2296 },
2297 None => {
2298 if let Some(net_token) = find_invalid_network(node) {
2300 self.handler.emit_err(crate::errors::invalid_network(self.token_span(&net_token)));
2301 } else {
2302 self.emit_unexpected_str(".aleo network", node.text(), span);
2303 }
2304 leo_ast::Identifier { name: Symbol::intern("aleo"), span, id: self.builder.next_id() }
2305 }
2306 };
2307
2308 Ok((program_name, network))
2309 }
2310
2311 fn program_decl_to_name_with_parent(
2313 &self,
2314 node: &SyntaxNode,
2315 ) -> Result<(leo_ast::Identifier, leo_ast::Identifier, Parents)> {
2316 debug_assert_eq!(node.kind(), PROGRAM_DECL);
2317 let (program_name, network) = self.program_decl_to_name(node)?;
2318
2319 let parents = if let Some(parent_list) = children(node).find(|n| n.kind() == PARENT_LIST) {
2320 self.collect_parent_list(&parent_list)?
2321 } else {
2322 vec![]
2323 };
2324
2325 Ok((program_name, network, parents))
2326 }
2327
2328 fn collect_parent_list(&self, node: &SyntaxNode) -> Result<Parents> {
2329 debug_assert_eq!(node.kind(), PARENT_LIST);
2330 children(node)
2331 .filter(|n| n.kind().is_type())
2332 .map(|n| self.to_type(&n).map(|t| (self.to_span(&n), t)))
2333 .collect::<Result<Vec<_>>>()
2334 }
2335
2336 fn collect_annotations(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::Annotation>> {
2338 children(node).filter(|n| n.kind() == ANNOTATION).map(|n| self.to_annotation(&n)).collect()
2339 }
2340
2341 fn require_block(&self, node: &SyntaxNode, span: Span) -> Result<leo_ast::Block> {
2343 Ok(children(node)
2344 .find(|n| n.kind() == BLOCK)
2345 .map(|n| self.to_block(&n))
2346 .transpose()?
2347 .unwrap_or_else(|| self.error_block(span)))
2348 }
2349
2350 fn to_function(&self, node: &SyntaxNode, is_in_program_block: bool) -> Result<leo_ast::Function> {
2352 debug_assert!(matches!(node.kind(), FUNCTION_DEF | FINAL_FN_DEF | VIEW_FN_DEF | CONSTRUCTOR_DEF));
2353 let span = self.span_including_annotations(node, self.non_trivia_span(node));
2354 let id = self.builder.next_id();
2355
2356 let annotations = self.collect_annotations(node)?;
2357
2358 let variant = if is_in_program_block {
2364 match node.kind() {
2365 VIEW_FN_DEF => leo_ast::Variant::View,
2366 FINAL_FN_DEF => leo_ast::Variant::FinalFn,
2367 FUNCTION_DEF | CONSTRUCTOR_DEF => leo_ast::Variant::EntryPoint,
2368 kind => unreachable!("unexpected function node kind in program block: {kind:?}"),
2369 }
2370 } else {
2371 match node.kind() {
2372 FINAL_FN_DEF => leo_ast::Variant::FinalFn,
2373 FUNCTION_DEF | VIEW_FN_DEF => leo_ast::Variant::Fn,
2374 kind => unreachable!("unexpected function node kind outside program block: {kind:?}"),
2375 }
2376 };
2377
2378 let identifier = self.require_ident(node, "function name");
2379 self.validate_identifier(&identifier);
2380
2381 let const_parameters = self.extract_const_parameters(node)?;
2382
2383 let input = children(node)
2385 .find(|n| n.kind() == PARAM_LIST)
2386 .map(|n| self.param_list_to_inputs(&n))
2387 .transpose()?
2388 .unwrap_or_default();
2389
2390 let (output, output_type) = if let Some(return_type_node) = children(node).find(|n| n.kind() == RETURN_TYPE) {
2396 self.return_type_to_outputs(&return_type_node)?
2398 } else if let Some(type_node) = children(node).find(|n| n.kind().is_type()) {
2399 let type_ = self.to_type(&type_node)?;
2401 let (mode, mode_start) = self.return_mode_before(node, &type_node);
2403 let type_span = self.content_span(&type_node);
2404 let output_span = match mode_start {
2405 Some(start) => Span::new(start, type_span.hi),
2406 None => type_span,
2407 };
2408 let output =
2409 vec![leo_ast::Output { mode, type_: type_.clone(), span: output_span, id: self.builder.next_id() }];
2410 (output, type_)
2411 } else {
2412 (Vec::new(), leo_ast::Type::Unit)
2413 };
2414
2415 let block = self.require_block(node, span)?;
2416
2417 Ok(leo_ast::Function {
2418 annotations,
2419 variant,
2420 identifier,
2421 const_parameters,
2422 input,
2423 output,
2424 output_type,
2425 block,
2426 span,
2427 id,
2428 })
2429 }
2430
2431 fn return_mode_before(&self, parent: &SyntaxNode, type_node: &SyntaxNode) -> (leo_ast::Mode, Option<u32>) {
2437 let type_start = type_node.text_range().start();
2438 let mut mode = leo_ast::Mode::None;
2439 let mut mode_start = None;
2440 for token in tokens(parent) {
2441 let token_end = token.text_range().end();
2442 if token_end > type_start {
2443 break;
2444 }
2445 if let Some(m) = token_kind_to_mode(token.kind()) {
2446 mode = m;
2447 mode_start = Some(u32::from(token.text_range().start()) + self.start_pos);
2448 }
2449 }
2450 (mode, mode_start)
2451 }
2452
2453 fn return_type_to_outputs(&self, node: &SyntaxNode) -> Result<(Vec<leo_ast::Output>, leo_ast::Type)> {
2455 debug_assert_eq!(node.kind(), RETURN_TYPE);
2456
2457 let mut outputs = Vec::new();
2460 let mut current_mode = leo_ast::Mode::None;
2461 let mut current_mode_start: Option<u32> = None;
2462
2463 for child in node.children_with_tokens() {
2464 match &child {
2465 SyntaxElement::Token(token) if !token.kind().is_trivia() => {
2466 if let Some(m) = token_kind_to_mode(token.kind()) {
2467 current_mode = m;
2468 current_mode_start = Some(u32::from(token.text_range().start()) + self.start_pos);
2469 }
2470 }
2471 SyntaxElement::Node(child_node) if child_node.kind().is_type() => {
2472 let type_ = self.to_type(child_node)?;
2473 let type_span = self.content_span(child_node);
2474 let output_span = match current_mode_start.take() {
2475 Some(start) => Span::new(start, type_span.hi),
2476 None => type_span,
2477 };
2478 outputs.push(leo_ast::Output {
2479 mode: current_mode,
2480 type_,
2481 span: output_span,
2482 id: self.builder.next_id(),
2483 });
2484 current_mode = leo_ast::Mode::None;
2485 }
2486 _ => {}
2487 }
2488 }
2489
2490 let output_type = match outputs.len() {
2491 0 => leo_ast::Type::Unit,
2492 1 => outputs[0].type_.clone(),
2493 _ => leo_ast::TupleType::new(outputs.iter().map(|o| o.type_.clone()).collect()).into(),
2494 };
2495
2496 Ok((outputs, output_type))
2497 }
2498
2499 fn to_annotation(&self, node: &SyntaxNode) -> Result<leo_ast::Annotation> {
2501 debug_assert_eq!(node.kind(), ANNOTATION);
2502 let span = self.trimmed_span(node);
2503 let id = self.builder.next_id();
2504
2505 let identifier = match tokens(node).find(|t| t.kind() == IDENT || t.kind().is_keyword()) {
2508 Some(name_token) => {
2509 let name = Symbol::intern(name_token.text());
2510 let name_span = self.token_span(&name_token);
2511 leo_ast::Identifier { name, span: name_span, id: self.builder.next_id() }
2512 }
2513 None => {
2514 self.emit_unexpected_str("annotation name", node.text(), span);
2515 self.error_identifier(span)
2516 }
2517 };
2518
2519 let map = children(node)
2521 .filter(|n| n.kind() == ANNOTATION_PAIR)
2522 .filter_map(|pair| {
2523 let key =
2524 tokens(&pair).find(|t| t.kind() == IDENT || t.kind() == KW_ADDRESS || t.kind() == KW_MAPPING)?;
2525 let val = tokens(&pair).find(|t| t.kind() == STRING)?;
2526 let text = val.text();
2527 Some((Symbol::intern(key.text()), text[1..text.len() - 1].to_string()))
2528 })
2529 .collect();
2530
2531 Ok(leo_ast::Annotation { identifier, map, span, id })
2532 }
2533
2534 fn param_list_to_inputs(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::Input>> {
2536 debug_assert_eq!(node.kind(), PARAM_LIST);
2537
2538 children(node)
2539 .filter(|n| matches!(n.kind(), PARAM | PARAM_PUBLIC | PARAM_PRIVATE | PARAM_CONSTANT))
2540 .map(|n| self.param_to_input(&n))
2541 .collect()
2542 }
2543
2544 fn param_to_input(&self, node: &SyntaxNode) -> Result<leo_ast::Input> {
2546 debug_assert!(matches!(node.kind(), PARAM | PARAM_PUBLIC | PARAM_PRIVATE | PARAM_CONSTANT));
2547 let span = self.non_trivia_span(node);
2548 let id = self.builder.next_id();
2549
2550 let mode = node_kind_to_mode(node.kind());
2551
2552 let identifier = self.require_ident(node, "parameter name");
2553 self.validate_identifier(&identifier);
2554
2555 let type_ = self.require_type(node, "parameter type")?;
2556
2557 Ok(leo_ast::Input { identifier, mode, type_, span, id })
2558 }
2559
2560 fn to_const_parameters(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::ConstParameter>> {
2562 debug_assert_eq!(node.kind(), CONST_PARAM_LIST);
2563
2564 children(node)
2565 .filter(|n| n.kind() == CONST_PARAM)
2566 .map(|n| {
2567 let span = self.non_trivia_span(&n);
2568 let id = self.builder.next_id();
2569
2570 let identifier = self.require_ident(&n, "const parameter name");
2571
2572 let type_ = self.require_type(&n, "const parameter type")?;
2573
2574 Ok(leo_ast::ConstParameter { identifier, type_, span, id })
2575 })
2576 .collect()
2577 }
2578
2579 fn extract_const_parameters(&self, node: &SyntaxNode) -> Result<Vec<leo_ast::ConstParameter>> {
2581 children(node)
2582 .find(|n| n.kind() == CONST_PARAM_LIST)
2583 .map(|n| self.to_const_parameters(&n))
2584 .transpose()
2585 .map(|opt| opt.unwrap_or_default())
2586 }
2587
2588 fn to_composite(&self, node: &SyntaxNode) -> Result<leo_ast::Composite> {
2590 debug_assert!(matches!(node.kind(), STRUCT_DEF | RECORD_DEF));
2591 let span = self.non_trivia_span(node);
2592 let id = self.builder.next_id();
2593
2594 let is_record = node.kind() == RECORD_DEF;
2595
2596 let identifier = self.require_ident(node, "struct/record name");
2597 self.validate_identifier(&identifier);
2598
2599 let const_parameters = self.extract_const_parameters(node)?;
2600
2601 let members = children(node)
2603 .filter(|n| {
2604 matches!(
2605 n.kind(),
2606 STRUCT_MEMBER | STRUCT_MEMBER_PUBLIC | STRUCT_MEMBER_PRIVATE | STRUCT_MEMBER_CONSTANT
2607 )
2608 })
2609 .map(|n| self.struct_member_to_member(&n))
2610 .collect::<Result<Vec<_>>>()?;
2611
2612 Ok(leo_ast::Composite { identifier, const_parameters, members, is_record, span, id })
2613 }
2614
2615 fn struct_member_to_member(&self, node: &SyntaxNode) -> Result<leo_ast::Member> {
2617 debug_assert!(matches!(
2618 node.kind(),
2619 STRUCT_MEMBER | STRUCT_MEMBER_PUBLIC | STRUCT_MEMBER_PRIVATE | STRUCT_MEMBER_CONSTANT
2620 ));
2621 let span = self.non_trivia_span(node);
2622 let id = self.builder.next_id();
2623
2624 let mode = node_kind_to_mode(node.kind());
2625
2626 let identifier = self.require_ident(node, "member name");
2627 self.validate_identifier(&identifier);
2628
2629 let type_ = self.require_type(node, "member type")?;
2630
2631 Ok(leo_ast::Member { mode, identifier, type_, span, id })
2632 }
2633
2634 fn to_global_const(&self, node: &SyntaxNode) -> Result<leo_ast::ConstDeclaration> {
2636 debug_assert_eq!(node.kind(), GLOBAL_CONST);
2637 let span = self.non_trivia_span(node);
2638 let id = self.builder.next_id();
2639
2640 let place = self.require_ident(node, "const name");
2641 self.validate_definition_identifier(&place);
2642
2643 let type_ = self.require_type(node, "const type")?;
2644
2645 let value = self.require_expression(node, "const value")?;
2646
2647 Ok(leo_ast::ConstDeclaration { place, type_, value, span, id })
2648 }
2649
2650 fn parse_mapping_def(
2652 &self,
2653 node: &SyntaxNode,
2654 ) -> Result<(leo_ast::Identifier, leo_ast::Type, leo_ast::Type, Span, NodeID)> {
2655 debug_assert_eq!(node.kind(), MAPPING_DEF);
2656 let span = self.non_trivia_span(node);
2657 let id = self.builder.next_id();
2658 let identifier = self.require_ident(node, "name in mapping");
2659 let mut type_nodes = children(node).filter(|n| n.kind().is_type());
2660 let key_type = match type_nodes.next() {
2661 Some(key_node) => self.to_type(&key_node)?,
2662 None => {
2663 self.emit_unexpected_str("key type in mapping", node.text(), span);
2664 leo_ast::Type::Err
2665 }
2666 };
2667 let value_type = match type_nodes.next() {
2668 Some(value_node) => self.to_type(&value_node)?,
2669 None => {
2670 self.emit_unexpected_str("value type in mapping", node.text(), span);
2671 leo_ast::Type::Err
2672 }
2673 };
2674 Ok((identifier, key_type, value_type, span, id))
2675 }
2676
2677 fn to_mapping(&self, node: &SyntaxNode) -> Result<leo_ast::Mapping> {
2679 let (identifier, key_type, value_type, span, id) = self.parse_mapping_def(node)?;
2680 Ok(leo_ast::Mapping { identifier, key_type, value_type, span, id })
2681 }
2682
2683 fn to_mapping_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::MappingPrototype> {
2685 let (identifier, key_type, value_type, span, id) = self.parse_mapping_def(node)?;
2686 Ok(leo_ast::MappingPrototype { identifier, key_type, value_type, span, id })
2687 }
2688
2689 fn parse_storage_def(&self, node: &SyntaxNode) -> Result<(leo_ast::Identifier, leo_ast::Type, Span, NodeID)> {
2691 debug_assert_eq!(node.kind(), STORAGE_DEF);
2692 let span = self.non_trivia_span(node);
2693 let id = self.builder.next_id();
2694 let identifier = self.require_ident(node, "name in storage");
2695 let type_ = self.require_type(node, "type in storage")?;
2696 Ok((identifier, type_, span, id))
2697 }
2698
2699 fn to_storage(&self, node: &SyntaxNode) -> Result<leo_ast::StorageVariable> {
2701 let (identifier, type_, span, id) = self.parse_storage_def(node)?;
2702 Ok(leo_ast::StorageVariable { identifier, type_, span, id })
2703 }
2704
2705 fn to_storage_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::StorageVariablePrototype> {
2707 let (identifier, type_, span, id) = self.parse_storage_def(node)?;
2708 Ok(leo_ast::StorageVariablePrototype { identifier, type_, span, id })
2709 }
2710
2711 fn to_constructor(&self, node: &SyntaxNode) -> Result<leo_ast::Constructor> {
2713 debug_assert_eq!(node.kind(), CONSTRUCTOR_DEF);
2714 let span = self.span_including_annotations(node, self.non_trivia_span(node));
2715 let id = self.builder.next_id();
2716
2717 let annotations = self.collect_annotations(node)?;
2718 let block = self.require_block(node, span)?;
2719
2720 Ok(leo_ast::Constructor { annotations, block, span, id })
2721 }
2722
2723 fn to_interface(&self, node: &SyntaxNode) -> Result<leo_ast::Interface> {
2729 debug_assert_eq!(node.kind(), INTERFACE_DEF);
2730 let span = self.to_span(node);
2731
2732 let identifier = self.require_ident(node, "interface name");
2734
2735 let parents = if let Some(parent_list) = children(node).find(|n| n.kind() == PARENT_LIST) {
2738 self.collect_parent_list(&parent_list)?
2739 } else {
2740 vec![]
2741 };
2742
2743 let mut functions = Vec::new();
2744 let mut records = Vec::new();
2745 let mut mappings = Vec::new();
2746 let mut storages = Vec::new();
2747
2748 for child in children(node) {
2749 match child.kind() {
2750 FN_PROTOTYPE_DEF => {
2751 let proto = self.to_function_prototype(&child)?;
2752 functions.push((proto.identifier.name, proto));
2753 }
2754 RECORD_PROTOTYPE_DEF => {
2755 let proto = self.to_record_prototype(&child)?;
2756 records.push((proto.identifier.name, proto));
2757 }
2758 MAPPING_DEF => {
2759 let mapping = self.to_mapping_prototype(&child)?;
2760 mappings.push(mapping);
2761 }
2762 STORAGE_DEF => {
2763 let storage = self.to_storage_prototype(&child)?;
2764 storages.push(storage);
2765 }
2766 _ => {}
2767 }
2768 }
2769
2770 Ok(leo_ast::Interface {
2771 identifier,
2772 parents,
2773 span,
2774 id: self.builder.next_id(),
2775 functions,
2776 records,
2777 mappings,
2778 storages,
2779 })
2780 }
2781
2782 fn to_function_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::FunctionPrototype> {
2784 debug_assert_eq!(node.kind(), FN_PROTOTYPE_DEF);
2785 let span = self.to_span(node);
2786
2787 let is_view = tokens(node).any(|t| t.kind() == KW_VIEW);
2788 let variant = if is_view { leo_ast::Variant::View } else { leo_ast::Variant::EntryPoint };
2789 let identifier = self.require_ident(node, "function name");
2790
2791 let const_parameters = self.extract_const_parameters(node)?;
2793
2794 let input = children(node)
2796 .find(|n| n.kind() == PARAM_LIST)
2797 .map(|n| self.param_list_to_inputs(&n))
2798 .transpose()?
2799 .unwrap_or_default();
2800
2801 let output = if let Some(return_type_node) = children(node).find(|n| n.kind() == RETURN_TYPE) {
2804 self.return_type_to_outputs(&return_type_node)?.0
2806 } else if let Some(type_node) = children(node).find(|n| n.kind().is_type()) {
2807 let type_ = self.to_type(&type_node)?;
2809 let (mode, mode_start) = self.return_mode_before(node, &type_node);
2811 let type_span = self.content_span(&type_node);
2812 let output_span = match mode_start {
2813 Some(start) => Span::new(start, type_span.hi),
2814 None => type_span,
2815 };
2816 vec![leo_ast::Output { mode, type_, span: output_span, id: self.builder.next_id() }]
2817 } else {
2818 Vec::new()
2819 };
2820
2821 Ok(leo_ast::FunctionPrototype::new(
2822 vec![], variant,
2824 identifier,
2825 const_parameters,
2826 input,
2827 output,
2828 span,
2829 self.builder.next_id(),
2830 ))
2831 }
2832
2833 fn to_record_prototype(&self, node: &SyntaxNode) -> Result<leo_ast::RecordPrototype> {
2835 debug_assert_eq!(node.kind(), RECORD_PROTOTYPE_DEF);
2836
2837 let span = self.to_span(node);
2838 let identifier = self.require_ident(node, "record name");
2839 let members = children(node)
2840 .filter(|n| {
2841 matches!(
2842 n.kind(),
2843 STRUCT_MEMBER | STRUCT_MEMBER_PUBLIC | STRUCT_MEMBER_PRIVATE | STRUCT_MEMBER_CONSTANT
2844 )
2845 })
2846 .map(|n| self.struct_member_to_member(&n))
2847 .collect::<Result<Vec<_>>>()?;
2848
2849 let is_redundant = members.is_empty()
2851 || members.iter().all(|m| {
2852 m.identifier.name == sym::owner && m.type_ == leo_ast::Type::Address && m.mode == leo_ast::Mode::None
2853 });
2854 if is_redundant && !members.is_empty() {
2855 self.handler.emit_warning(crate::errors::record_prototype_redundant(identifier.name, span));
2857 return Ok(leo_ast::RecordPrototype { identifier, span, members: Vec::new(), id: self.builder.next_id() });
2858 } else if is_redundant {
2859 let had_braces = node.children_with_tokens().any(|c| c.kind() == L_BRACE);
2862 if had_braces {
2863 self.handler.emit_warning(crate::errors::record_prototype_redundant(identifier.name, span));
2864 }
2865 }
2866
2867 Ok(leo_ast::RecordPrototype { identifier, span, members, id: self.builder.next_id() })
2868 }
2869}
2870
2871fn clamped_span(range: TextRange, start_pos: u32, source_len: u32) -> Span {
2877 let end = start_pos + source_len;
2878 let lo = (u32::from(range.start()) + start_pos).min(end);
2879 let hi = (u32::from(range.end()) + start_pos).min(end).max(lo);
2880 Span::new(lo, hi)
2881}
2882
2883fn emit_lex_errors(handler: &Handler, lex_errors: &[leo_parser_rowan::LexError], start_pos: u32, source_len: u32) {
2885 use leo_parser_rowan::LexErrorKind;
2886 for error in lex_errors {
2887 let span = clamped_span(error.range, start_pos, source_len);
2888
2889 match &error.kind {
2890 LexErrorKind::InvalidDigit { digit, radix, token } => {
2891 handler.emit_err(crate::errors::wrong_digit_for_radix_span(*digit, *radix, token, span));
2892 }
2893 LexErrorKind::CouldNotLex { content } => {
2894 handler.emit_err(crate::errors::could_not_lex_span(content, span));
2895 }
2896 LexErrorKind::BidiOverride => {
2897 handler.emit_err(crate::errors::lexer_bidi_override_span(span));
2898 }
2899 }
2900 }
2901}
2902
2903fn emit_parse_errors(
2906 handler: &Handler,
2907 errors: &[leo_parser_rowan::ParseError],
2908 start_pos: u32,
2909 source_len: u32,
2910 lex_errors: &[leo_parser_rowan::LexError],
2911) {
2912 use std::collections::HashSet;
2913
2914 let has_lex_errors = !lex_errors.is_empty();
2915
2916 let lex_ranges: Vec<(u32, u32)> = lex_errors
2918 .iter()
2919 .map(|e| {
2920 let lo = u32::from(e.range.start()).saturating_add(start_pos);
2921 let hi = u32::from(e.range.end()).saturating_add(start_pos);
2922 (lo, hi)
2923 })
2924 .collect();
2925
2926 let mut emitted_ranges: HashSet<(u32, u32)> = HashSet::new();
2928 let mut count = 0;
2929 let max_errors = 10;
2930
2931 for error in errors {
2932 if count >= max_errors {
2933 break;
2934 }
2935
2936 let span = clamped_span(error.range, start_pos, source_len);
2937 let range_key = (span.lo, span.hi);
2938
2939 if emitted_ranges.contains(&range_key) {
2941 continue;
2942 }
2943
2944 if has_lex_errors && span.lo == span.hi && span.hi == start_pos + source_len {
2947 continue;
2948 }
2949
2950 if lex_ranges.iter().any(|&(lo, hi)| span.lo < hi && span.hi > lo) {
2953 continue;
2954 }
2955
2956 emitted_ranges.insert(range_key);
2957
2958 let is_eof_error = match &error.found {
2961 Some(f) => f.is_empty() || f == "end of file",
2962 None => false,
2963 } || (span.lo == span.hi && span.hi >= start_pos + source_len);
2964
2965 if is_eof_error {
2966 handler.emit_err(crate::errors::unexpected_eof(span));
2967 count += 1;
2968 continue;
2969 }
2970
2971 if let Some(found) = &error.found {
2973 if error.expected.is_empty() {
2974 handler.emit_err(crate::errors::custom(&error.message, span));
2977 } else {
2978 let expected_str = error.expected.join(", ");
2979 handler.emit_err(crate::errors::unexpected(found, expected_str, span));
2980 }
2981 count += 1;
2982 continue;
2983 }
2984
2985 handler.emit_err(crate::errors::custom(&error.message, span));
2987 count += 1;
2988 }
2989}
2990
2991fn conversion_context<'a>(
2993 handler: &'a Handler,
2994 node_builder: &'a NodeBuilder,
2995 lex_errors: &[leo_parser_rowan::LexError],
2996 parse_errors: &[leo_parser_rowan::ParseError],
2997 start_pos: u32,
2998 source_len: u32,
2999) -> ConversionContext<'a> {
3000 emit_lex_errors(handler, lex_errors, start_pos, source_len);
3001 emit_parse_errors(handler, parse_errors, start_pos, source_len, lex_errors);
3002 let has_errors = !parse_errors.is_empty() || !lex_errors.is_empty();
3003 ConversionContext::new(handler, node_builder, start_pos, has_errors)
3004}
3005
3006pub fn parse_expression(
3008 handler: Handler,
3009 node_builder: &NodeBuilder,
3010 source: &str,
3011 start_pos: u32,
3012 _network: NetworkName,
3013) -> Result<leo_ast::Expression> {
3014 let parse = leo_parser_rowan::parse_expression_entry(source);
3015 let ctx =
3016 conversion_context(&handler, node_builder, parse.lex_errors(), parse.errors(), start_pos, source.len() as u32);
3017 ctx.to_expression(&parse.syntax())
3018}
3019
3020pub fn parse_statement(
3022 handler: Handler,
3023 node_builder: &NodeBuilder,
3024 source: &str,
3025 start_pos: u32,
3026 _network: NetworkName,
3027) -> Result<leo_ast::Statement> {
3028 let parse = leo_parser_rowan::parse_statement_entry(source);
3029 let ctx =
3030 conversion_context(&handler, node_builder, parse.lex_errors(), parse.errors(), start_pos, source.len() as u32);
3031 ctx.to_statement(&parse.syntax())
3032}
3033
3034pub fn parse_module(
3036 handler: Handler,
3037 node_builder: &NodeBuilder,
3038 source: &str,
3039 start_pos: u32,
3040 program_name: Symbol,
3041 path: Vec<Symbol>,
3042 _network: NetworkName,
3043) -> Result<leo_ast::Module> {
3044 let parse = leo_parser_rowan::parse_module_entry(source);
3045 let ctx =
3046 conversion_context(&handler, node_builder, parse.lex_errors(), parse.errors(), start_pos, source.len() as u32);
3047 ctx.to_module(&parse.syntax(), program_name, path)
3048}
3049
3050pub fn parse_program(
3052 handler: Handler,
3053 node_builder: &NodeBuilder,
3054 source: &SourceFile,
3055 modules: &[std::rc::Rc<SourceFile>],
3056 _network: NetworkName,
3057) -> Result<leo_ast::Program> {
3058 let parse = leo_parser_rowan::parse_file(&source.src);
3060 let main_context = conversion_context(
3061 &handler,
3062 node_builder,
3063 parse.lex_errors(),
3064 parse.errors(),
3065 source.absolute_start,
3066 source.src.len() as u32,
3067 );
3068 let mut program = main_context.to_main(&parse.syntax())?;
3069 let program_name = *program.program_scopes.first().unwrap().0;
3070
3071 let root_dir = match &source.name {
3073 FileName::Real(path) => path.parent().map(|p| p.to_path_buf()),
3074 _ => None,
3075 };
3076
3077 for module in modules {
3078 let module_parse = leo_parser_rowan::parse_module_entry(&module.src);
3079 let module_context = conversion_context(
3080 &handler,
3081 node_builder,
3082 module_parse.lex_errors(),
3083 module_parse.errors(),
3084 module.absolute_start,
3085 module.src.len() as u32,
3086 );
3087
3088 if let Some(key) = compute_module_key(&module.name, root_dir.as_deref()) {
3089 for segment in &key {
3090 if leo_parser_rowan::is_keyword(&segment.to_string()) {
3091 return Err(crate::errors::keyword_used_as_module_name(key.iter().format("::"), segment).into());
3092 }
3093 }
3094 let module_ast = module_context.to_module(&module_parse.syntax(), program_name, key.clone())?;
3095 program.modules.insert(key, module_ast);
3096 }
3097 }
3098
3099 Ok(program)
3100}
3101
3102pub fn parse_library(
3104 handler: Handler,
3105 node_builder: &NodeBuilder,
3106 library_name: Symbol,
3107 source: &SourceFile,
3108 modules: &[std::rc::Rc<SourceFile>],
3109 _network: NetworkName,
3110) -> Result<leo_ast::Library> {
3111 let parse = leo_parser_rowan::parse_file(&source.src);
3113 let main_context = conversion_context(
3114 &handler,
3115 node_builder,
3116 parse.lex_errors(),
3117 parse.errors(),
3118 source.absolute_start,
3119 source.src.len() as u32,
3120 );
3121
3122 let mut library = main_context.to_library(library_name, &parse.syntax())?;
3123
3124 let root_dir = match &source.name {
3126 FileName::Real(path) => path.parent().map(|p| p.to_path_buf()),
3127 _ => None,
3128 };
3129
3130 for module_sf in modules {
3132 let module_parse = leo_parser_rowan::parse_module_entry(&module_sf.src);
3133 let module_context = conversion_context(
3134 &handler,
3135 node_builder,
3136 module_parse.lex_errors(),
3137 module_parse.errors(),
3138 module_sf.absolute_start,
3139 module_sf.src.len() as u32,
3140 );
3141
3142 if let Some(key) = compute_module_key(&module_sf.name, root_dir.as_deref()) {
3143 for segment in &key {
3144 if leo_parser_rowan::is_keyword(&segment.to_string()) {
3145 return Err(crate::errors::keyword_used_as_module_name(key.iter().format("::"), segment).into());
3146 }
3147 }
3148 let module_ast = module_context.to_module(&module_parse.syntax(), library_name, key.clone())?;
3151 library.modules.insert(key, module_ast);
3152 }
3153 }
3154
3155 Ok(library)
3156}
3157
3158fn children(node: &SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ {
3164 node.children().filter(|n| !n.kind().is_trivia())
3165}
3166
3167fn tokens(node: &SyntaxNode) -> impl Iterator<Item = SyntaxToken> + '_ {
3169 node.children_with_tokens().filter_map(|elem| elem.into_token()).filter(|t| !t.kind().is_trivia())
3170}
3171
3172fn find_name_after_dot(node: &SyntaxNode) -> Option<SyntaxToken> {
3174 let dot_end = tokens(node).find(|t| t.kind() == DOT)?.text_range().end();
3175 tokens(node).filter(|t| t.text_range().start() >= dot_end).find(|t| t.kind() == IDENT || t.kind().is_keyword())
3176}
3177
3178fn first_non_trivia_token(node: &SyntaxNode) -> Option<SyntaxToken> {
3180 node.children_with_tokens().find_map(|e| e.into_token().filter(|t| !t.kind().is_trivia()))
3181}
3182
3183fn last_non_trivia_token(node: &SyntaxNode) -> Option<SyntaxToken> {
3185 node.children_with_tokens().filter_map(|e| e.into_token().filter(|t| !t.kind().is_trivia())).last()
3186}
3187
3188fn find_invalid_network(node: &SyntaxNode) -> Option<SyntaxToken> {
3190 let mut saw_dot = false;
3191 tokens(node).find(|t| {
3192 if t.kind() == DOT {
3193 saw_dot = true;
3194 return false;
3195 }
3196 saw_dot && t.kind() == IDENT
3197 })
3198}
3199
3200fn token_kind_to_mode(kind: SyntaxKind) -> Option<leo_ast::Mode> {
3202 match kind {
3203 KW_PUBLIC => Some(leo_ast::Mode::Public),
3204 KW_PRIVATE => Some(leo_ast::Mode::Private),
3205 KW_CONSTANT => Some(leo_ast::Mode::Constant),
3206 _ => None,
3207 }
3208}
3209
3210fn node_kind_to_mode(kind: SyntaxKind) -> leo_ast::Mode {
3212 match kind {
3213 PARAM_PUBLIC | STRUCT_MEMBER_PUBLIC => leo_ast::Mode::Public,
3214 PARAM_PRIVATE | STRUCT_MEMBER_PRIVATE => leo_ast::Mode::Private,
3215 PARAM_CONSTANT | STRUCT_MEMBER_CONSTANT => leo_ast::Mode::Constant,
3216 _ => leo_ast::Mode::None,
3217 }
3218}
3219
3220fn keyword_to_path_symbol(kind: SyntaxKind) -> Option<Symbol> {
3222 match kind {
3223 KW_SELF => Some(sym::SelfLower),
3224 KW_BLOCK => Some(sym::block),
3225 KW_NETWORK => Some(sym::network),
3226 KW_FINAL_UPPER => Some(sym::Final),
3227 _ => None,
3228 }
3229}
3230
3231fn is_assign_op(kind: SyntaxKind) -> bool {
3233 matches!(
3234 kind,
3235 EQ | PLUS_EQ
3236 | MINUS_EQ
3237 | STAR_EQ
3238 | SLASH_EQ
3239 | PERCENT_EQ
3240 | STAR2_EQ
3241 | AMP_EQ
3242 | PIPE_EQ
3243 | CARET_EQ
3244 | SHL_EQ
3245 | SHR_EQ
3246 | AMP2_EQ
3247 | PIPE2_EQ
3248 )
3249}
3250
3251fn keyword_to_primitive_type(kind: SyntaxKind) -> Option<leo_ast::Type> {
3253 let ty = match kind {
3254 KW_ADDRESS => leo_ast::Type::Address,
3255 KW_BOOL => leo_ast::Type::Boolean,
3256 KW_FIELD => leo_ast::Type::Field,
3257 KW_GROUP => leo_ast::Type::Group,
3258 KW_SCALAR => leo_ast::Type::Scalar,
3259 KW_SIGNATURE => leo_ast::Type::Signature,
3260 KW_STRING => leo_ast::Type::String,
3261 KW_DYN => leo_ast::Type::DynRecord,
3262 KW_IDENTIFIER => leo_ast::Type::Identifier,
3263 KW_U8 => leo_ast::Type::Integer(leo_ast::IntegerType::U8),
3264 KW_U16 => leo_ast::Type::Integer(leo_ast::IntegerType::U16),
3265 KW_U32 => leo_ast::Type::Integer(leo_ast::IntegerType::U32),
3266 KW_U64 => leo_ast::Type::Integer(leo_ast::IntegerType::U64),
3267 KW_U128 => leo_ast::Type::Integer(leo_ast::IntegerType::U128),
3268 KW_I8 => leo_ast::Type::Integer(leo_ast::IntegerType::I8),
3269 KW_I16 => leo_ast::Type::Integer(leo_ast::IntegerType::I16),
3270 KW_I32 => leo_ast::Type::Integer(leo_ast::IntegerType::I32),
3271 KW_I64 => leo_ast::Type::Integer(leo_ast::IntegerType::I64),
3272 KW_I128 => leo_ast::Type::Integer(leo_ast::IntegerType::I128),
3273 _ => return None,
3274 };
3275 Some(ty)
3276}
3277
3278fn token_to_binary_op(kind: SyntaxKind) -> leo_ast::BinaryOperation {
3280 match kind {
3281 EQ2 => leo_ast::BinaryOperation::Eq,
3282 BANG_EQ => leo_ast::BinaryOperation::Neq,
3283 LT => leo_ast::BinaryOperation::Lt,
3284 LT_EQ => leo_ast::BinaryOperation::Lte,
3285 GT => leo_ast::BinaryOperation::Gt,
3286 GT_EQ => leo_ast::BinaryOperation::Gte,
3287 PLUS => leo_ast::BinaryOperation::Add,
3288 MINUS => leo_ast::BinaryOperation::Sub,
3289 STAR => leo_ast::BinaryOperation::Mul,
3290 SLASH => leo_ast::BinaryOperation::Div,
3291 PERCENT => leo_ast::BinaryOperation::Rem,
3292 PIPE2 => leo_ast::BinaryOperation::Or,
3293 AMP2 => leo_ast::BinaryOperation::And,
3294 PIPE => leo_ast::BinaryOperation::BitwiseOr,
3295 AMP => leo_ast::BinaryOperation::BitwiseAnd,
3296 STAR2 => leo_ast::BinaryOperation::Pow,
3297 SHL => leo_ast::BinaryOperation::Shl,
3298 SHR => leo_ast::BinaryOperation::Shr,
3299 CARET => leo_ast::BinaryOperation::Xor,
3300 _ => panic!("unexpected binary operator: {:?}", kind),
3301 }
3302}
3303
3304fn compute_module_key(name: &FileName, root_dir: Option<&std::path::Path>) -> Option<Vec<Symbol>> {
3306 let path = match name {
3307 FileName::Custom(name) => std::path::Path::new(name).to_path_buf(),
3308 FileName::Real(path) => {
3309 let root = root_dir?;
3310 path.strip_prefix(root).ok()?.to_path_buf()
3311 }
3312 };
3313
3314 let mut key: Vec<Symbol> =
3315 path.components().map(|comp| Symbol::intern(&comp.as_os_str().to_string_lossy())).collect();
3316
3317 if let Some(last) = path.file_name()
3318 && let Some(stem) = std::path::Path::new(last).file_stem()
3319 {
3320 key.pop();
3321 key.push(Symbol::intern(&stem.to_string_lossy()));
3322 }
3323
3324 Some(key)
3325}
3326
3327fn is_library_item(kind: SyntaxKind) -> bool {
3329 matches!(kind, GLOBAL_CONST | STRUCT_DEF | FUNCTION_DEF | INTERFACE_DEF)
3330}
3331
3332fn is_program_item(kind: SyntaxKind) -> bool {
3334 matches!(
3335 kind,
3336 GLOBAL_CONST
3337 | FUNCTION_DEF
3338 | FINAL_FN_DEF
3339 | VIEW_FN_DEF
3340 | STRUCT_DEF
3341 | RECORD_DEF
3342 | INTERFACE_DEF
3343 | MAPPING_DEF
3344 | STORAGE_DEF
3345 | CONSTRUCTOR_DEF
3346 | PROGRAM_DECL
3347 | IMPORT
3348 )
3349}