(
&mut self,
fn_type: FunctionType,
visibility: Visibility,
)
| 722 | } |
| 723 | |
| 724 | fn func_declaration( |
| 725 | &mut self, |
| 726 | fn_type: FunctionType, |
| 727 | visibility: Visibility, |
| 728 | ) -> Option<Stmt<'gc>> { |
| 729 | // Save current function type |
| 730 | let previous_fn_type = self.fn_type; |
| 731 | self.fn_type = fn_type; |
| 732 | let type_name = match fn_type { |
| 733 | FunctionType::Method { .. } => "method", |
| 734 | FunctionType::Tool => "tool function", |
| 735 | _ => "function", |
| 736 | }; |
| 737 | |
| 738 | self.consume(TokenType::Identifier, &format!("Expect {type_name} name.")); |
| 739 | let name = self.previous; |
| 740 | self.scopes.push(name.lexeme.to_string()); |
| 741 | if self.fn_type.is_method() && name.lexeme == "new" { |
| 742 | self.fn_type = FunctionType::Constructor; |
| 743 | } |
| 744 | // Store the previous function info and create new one for this function |
| 745 | let previous_error_resolver = self.error_resolver.take(); |
| 746 | self.error_resolver = Some(FunctionErrorResolver::new(name)); |
| 747 | |
| 748 | self.consume(TokenType::OpenParen, "Expect '(' after function name."); |
| 749 | |
| 750 | // Use IndexMap for parameters and their types |
| 751 | // IndexMap is ordered by insertion order, |
| 752 | // which is matter for function call |
| 753 | let mut params = IndexMap::new(); |
| 754 | let mut keyword_args_count = 0; |
| 755 | let mut self_args_count = 0; |
| 756 | loop { |
| 757 | if self.check(TokenType::CloseParen) { |
| 758 | break; |
| 759 | } |
| 760 | if params.len() >= 255 { |
| 761 | self.error_at_current("Can't have more than 255 parameters."); |
| 762 | } |
| 763 | |
| 764 | if self.check(TokenType::Self_) { |
| 765 | self.advance(); |
| 766 | match self.fn_type { |
| 767 | FunctionType::Method { .. } if (self_args_count > 0 || !params.is_empty()) => { |
| 768 | self.error("'self' only allow as the first paramater."); |
| 769 | } |
| 770 | FunctionType::Function { .. } | FunctionType::Tool => { |
| 771 | self.error("'self' parameter is only allowed in class methods"); |
| 772 | } |
| 773 | FunctionType::Constructor => { |
| 774 | self.error("No need to declare 'self' parameter for class constructor."); |
| 775 | } |
| 776 | _ => { |
| 777 | // unreachable |
| 778 | } |
| 779 | } |
| 780 | |
| 781 | self_args_count += 1; |
no test coverage detected