// SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2024 The Gleam contributors //! AST traversal routines, referenced from [`syn::visit`](https://docs.rs/syn/latest/syn/visit/index.html) //! //! Each method of the [`Visit`] trait can be overridden to customize the //! behaviour when visiting the corresponding type of AST node. By default, //! every method recursively visits the substructure of the node by using the //! right visitor method. //! //! # Example //! //! Suppose we would like to collect all function names in a module, //! we can do the following: //! //! ```no_run //! use gleam_core::ast::{TypedFunction, visit::{self, Visit}}; //! //! struct FnCollector<'ast> { //! functions: Vec<&'ast TypedFunction> //! } //! //! impl<'ast> Visit<'ast> for FnCollector<'ast> { //! fn visit_typed_function(&mut self, fun: &'ast TypedFunction) { //! self.functions.push(fun); //! //! // Use the default behaviour to visit any nested functions //! visit::visit_typed_function(self, fun); //! } //! } //! //! fn print_all_module_functions() { //! let module = todo!("module"); //! let mut fn_collector = FnCollector { functions: vec![] }; //! //! // This will walk the AST and collect all functions //! fn_collector.visit_typed_module(module); //! //! // Print the collected functions //! println!("{:#?}", fn_collector.functions); //! } //! ``` use crate::{ analyse::Inferred, ast::{ BitArraySize, RecordBeingUpdated, TypeAstConstructorName, TypedBitArraySize, TypedConstantBitArraySegment, TypedDefinitions, TypedImport, TypedTailPattern, TypedTypeAlias, typed::InvalidExpression, }, exhaustiveness::CompiledCase, parse::LiteralFloatValue, type_::{ FieldMap, ModuleValueConstructor, PatternConstructor, TypedCallArg, ValueConstructor, error::VariableOrigin, }, }; use std::sync::Arc; use ecow::EcoString; use num_bigint::BigInt; use vec1::Vec1; use crate::type_::Type; use super::{ AssignName, BinOp, BitArrayOption, CallArg, Pattern, PipelineAssignmentKind, RecordUpdateArg, SrcSpan, Statement, TodoKind, TypeAst, TypedArg, TypedAssert, TypedAssignment, TypedClause, TypedClauseGuard, TypedConstant, TypedCustomType, TypedExpr, TypedExprBitArraySegment, TypedFunction, TypedModule, TypedModuleConstant, TypedPattern, TypedPatternBitArraySegment, TypedPipelineAssignment, TypedStatement, TypedUse, untyped::FunctionLiteralKind, }; pub trait Visit<'ast> { fn visit_typed_module(&mut self, module: &'ast TypedModule) { visit_typed_module(self, module); } fn visit_typed_function(&mut self, fun: &'ast TypedFunction) { visit_typed_function(self, fun); } fn visit_typed_module_constant(&mut self, constant: &'ast TypedModuleConstant) { visit_typed_module_constant(self, constant); } fn visit_typed_custom_type(&mut self, custom_type: &'ast TypedCustomType) { visit_typed_custom_type(self, custom_type); } fn visit_typed_type_alias(&mut self, type_alias: &'ast TypedTypeAlias) { visit_typed_type_alias(self, type_alias); } fn visit_typed_import(&mut self, import: &'ast TypedImport) { visit_typed_import(self, import); } fn visit_typed_expr(&mut self, expr: &'ast TypedExpr) { visit_typed_expr(self, expr); } fn visit_typed_expr_echo( &mut self, location: &'ast SrcSpan, type_: &'ast Arc, expression: &'ast Option>, message: &'ast Option>, ) { visit_typed_expr_echo(self, location, type_, expression, message); } fn visit_typed_expr_int( &mut self, location: &'ast SrcSpan, type_: &'ast Arc, string_value: &'ast EcoString, int_value: &'ast BigInt, ) { visit_typed_expr_int(self, location, type_, string_value, int_value); } fn visit_typed_expr_float( &mut self, location: &'ast SrcSpan, type_: &'ast Arc, value: &'ast EcoString, ) { visit_typed_expr_float(self, location, type_, value); } fn visit_typed_expr_string( &mut self, location: &'ast SrcSpan, type_: &'ast Arc, value: &'ast EcoString, ) { visit_typed_expr_string(self, location, type_, value); } fn visit_typed_expr_block( &mut self, location: &'ast SrcSpan, statements: &'ast [TypedStatement], ) { visit_typed_expr_block(self, location, statements); } fn visit_typed_expr_pipeline( &mut self, location: &'ast SrcSpan, first_value: &'ast TypedPipelineAssignment, assignments: &'ast [(TypedPipelineAssignment, PipelineAssignmentKind)], finally: &'ast TypedExpr, finally_kind: &'ast PipelineAssignmentKind, ) { visit_typed_expr_pipeline( self, location, first_value, assignments, finally, finally_kind, ); } fn visit_typed_expr_var( &mut self, location: &'ast SrcSpan, constructor: &'ast ValueConstructor, name: &'ast EcoString, ) { visit_typed_expr_var(self, location, constructor, name); } fn visit_typed_expr_fn( &mut self, location: &'ast SrcSpan, type_: &'ast Arc, kind: &'ast FunctionLiteralKind, arguments: &'ast [TypedArg], body: &'ast Vec1, return_annotation: &'ast Option, ) { visit_typed_expr_fn( self, location, type_, kind, arguments, body, return_annotation, ); } fn visit_typed_expr_list( &mut self, location: &'ast SrcSpan, type_: &'ast Arc, elements: &'ast [TypedExpr], tail: &'ast Option>, ) { visit_typed_expr_list(self, location, type_, elements, tail); } fn visit_typed_expr_call( &mut self, location: &'ast SrcSpan, type_: &'ast Arc, fun: &'ast TypedExpr, arguments: &'ast [TypedCallArg], open_parenthesis: &'ast Option, ) { visit_typed_expr_call(self, location, type_, fun, arguments, open_parenthesis); } fn visit_typed_expr_bin_op( &mut self, location: &'ast SrcSpan, type_: &'ast Arc, operator: &'ast BinOp, operator_start: &'ast u32, left: &'ast TypedExpr, right: &'ast TypedExpr, ) { visit_typed_expr_bin_op(self, location, type_, operator, operator_start, left, right); } fn visit_typed_expr_case( &mut self, location: &'ast SrcSpan, type_: &'ast Arc, subjects: &'ast [TypedExpr], clauses: &'ast [TypedClause], compiled_case: &'ast CompiledCase, ) { visit_typed_expr_case(self, location, type_, subjects, clauses, compiled_case); } #[allow(clippy::too_many_arguments)] fn visit_typed_expr_record_access( &mut self, location: &'ast SrcSpan, field_start: &'ast u32, type_: &'ast Arc, label: &'ast EcoString, index: &'ast u64, record: &'ast TypedExpr, documentation: &'ast Option, ) { visit_typed_expr_record_access( self, location, field_start, type_, label, index, record, documentation, ); } #[allow(clippy::too_many_arguments)] fn visit_typed_expr_module_select( &mut self, location: &'ast SrcSpan, field_start: &'ast u32, type_: &'ast Arc, label: &'ast EcoString, module_name: &'ast EcoString, module_alias: &'ast EcoString, constructor: &'ast ModuleValueConstructor, ) { visit_typed_expr_module_select( self, location, field_start, type_, label, module_name, module_alias, constructor, ); } fn visit_typed_expr_tuple( &mut self, location: &'ast SrcSpan, type_: &'ast Arc, elements: &'ast [TypedExpr], ) { visit_typed_expr_tuple(self, location, type_, elements); } fn visit_typed_expr_tuple_index( &mut self, location: &'ast SrcSpan, type_: &'ast Arc, index: &'ast u64, tuple: &'ast TypedExpr, ) { visit_typed_expr_tuple_index(self, location, type_, index, tuple); } fn visit_typed_expr_todo( &mut self, location: &'ast SrcSpan, message: &'ast Option>, kind: &'ast TodoKind, type_: &'ast Arc, ) { visit_typed_expr_todo(self, location, message, kind, type_); } fn visit_typed_expr_panic( &mut self, location: &'ast SrcSpan, message: &'ast Option>, type_: &'ast Arc, ) { visit_typed_expr_panic(self, location, message, type_); } fn visit_typed_expr_bit_array( &mut self, location: &'ast SrcSpan, type_: &'ast Arc, segments: &'ast [TypedExprBitArraySegment], ) { visit_typed_expr_bit_array(self, location, type_, segments); } #[allow(clippy::too_many_arguments)] fn visit_typed_expr_record_update( &mut self, location: &'ast SrcSpan, spread_start: &'ast u32, type_: &'ast Arc, updated_record: &'ast TypedExpr, updated_record_assigned_name: &'ast Option, constructor: &'ast TypedExpr, arguments: &'ast [TypedCallArg], ) { visit_typed_expr_record_update( self, location, spread_start, type_, updated_record, updated_record_assigned_name, constructor, arguments, ); } fn visit_typed_expr_negate_bool(&mut self, location: &'ast SrcSpan, value: &'ast TypedExpr) { visit_typed_expr_negate_bool(self, location, value); } fn visit_typed_expr_negate_int(&mut self, location: &'ast SrcSpan, value: &'ast TypedExpr) { visit_typed_expr_negate_int(self, location, value); } fn visit_typed_expr_invalid( &mut self, location: &'ast SrcSpan, type_: &'ast Arc, extra_information: &'ast Option, ) { visit_typed_expr_invalid(self, location, type_, extra_information); } fn visit_typed_statement(&mut self, statement: &'ast TypedStatement) { visit_typed_statement(self, statement); } fn visit_typed_assignment(&mut self, assignment: &'ast TypedAssignment) { visit_typed_assignment(self, assignment); } fn visit_typed_use(&mut self, use_: &'ast TypedUse) { visit_typed_use(self, use_); } fn visit_typed_assert(&mut self, assert: &'ast TypedAssert) { visit_typed_assert(self, assert); } fn visit_typed_pipeline_assignment(&mut self, assignment: &'ast TypedPipelineAssignment) { visit_typed_pipeline_assignment(self, assignment); } fn visit_typed_call_arg(&mut self, arg: &'ast TypedCallArg) { visit_typed_call_arg(self, arg); } fn visit_typed_clause(&mut self, clause: &'ast TypedClause) { visit_typed_clause(self, clause); } fn visit_typed_clause_guard(&mut self, guard: &'ast TypedClauseGuard) { visit_typed_clause_guard(self, guard); } fn visit_typed_clause_guard_bin_op( &mut self, left: &'ast TypedClauseGuard, right: &'ast TypedClauseGuard, operator: &'ast BinOp, operator_start: &'ast u32, location: &'ast SrcSpan, ) { visit_typed_clause_guard_bin_op(self, left, right, operator, operator_start, location); } fn visit_typed_clause_guard_var( &mut self, location: &'ast SrcSpan, name: &'ast EcoString, type_: &'ast Arc, definition_location: &'ast SrcSpan, origin: &'ast VariableOrigin, ) { visit_typed_clause_guard_var(self, location, name, type_, definition_location, origin); } fn visit_typed_clause_guard_tuple_index( &mut self, location: &'ast SrcSpan, index: &'ast u64, type_: &'ast Arc, tuple: &'ast TypedClauseGuard, ) { visit_typed_clause_guard_tuple_index(self, location, index, type_, tuple); } fn visit_typed_clause_guard_field_access( &mut self, label_location: &'ast SrcSpan, index: &'ast Option, label: &'ast EcoString, type_: &'ast Arc, container: &'ast TypedClauseGuard, ) { visit_typed_clause_guard_field_access(self, label_location, index, label, type_, container); } #[allow(clippy::too_many_arguments)] fn visit_typed_clause_guard_module_select( &mut self, location: &'ast SrcSpan, field_start: &'ast u32, definition_location: &'ast SrcSpan, type_: &'ast Arc, label: &'ast EcoString, module_name: &'ast EcoString, module_alias: &'ast EcoString, literal: &'ast TypedConstant, ) { visit_typed_clause_guard_module_select( self, location, field_start, definition_location, type_, label, module_name, module_alias, literal, ); } fn visit_typed_expr_bit_array_segment(&mut self, segment: &'ast TypedExprBitArraySegment) { visit_typed_expr_bit_array_segment(self, segment); } fn visit_typed_bit_array_option(&mut self, option: &'ast BitArrayOption) { visit_typed_bit_array_option(self, option); } fn visit_typed_pattern(&mut self, pattern: &'ast TypedPattern) { visit_typed_pattern(self, pattern); } fn visit_typed_pattern_int(&mut self, location: &'ast SrcSpan, value: &'ast EcoString) { visit_typed_pattern_int(self, location, value); } fn visit_typed_pattern_float(&mut self, location: &'ast SrcSpan, value: &'ast EcoString) { visit_typed_pattern_float(self, location, value); } fn visit_typed_pattern_string(&mut self, location: &'ast SrcSpan, value: &'ast EcoString) { visit_typed_pattern_string(self, location, value); } fn visit_typed_pattern_variable( &mut self, location: &'ast SrcSpan, name: &'ast EcoString, type_: &'ast Arc, origin: &'ast VariableOrigin, ) { visit_typed_pattern_variable(self, location, name, type_, origin); } fn visit_typed_pattern_bit_array_size(&mut self, size: &'ast TypedBitArraySize) { visit_typed_pattern_bit_array_size(self, size); } fn visit_typed_bit_array_size_int(&mut self, location: &'ast SrcSpan, value: &'ast EcoString) { visit_typed_bit_array_size_int(self, location, value); } fn visit_typed_bit_array_size_variable( &mut self, location: &'ast SrcSpan, name: &'ast EcoString, constructor: &'ast Option>, type_: &'ast Arc, ) { visit_typed_bit_array_size_variable(self, location, name, constructor, type_); } fn visit_typed_pattern_assign( &mut self, location: &'ast SrcSpan, name: &'ast EcoString, pattern: &'ast TypedPattern, ) { visit_typed_pattern_assign(self, location, name, pattern); } fn visit_typed_pattern_discard( &mut self, location: &'ast SrcSpan, name: &'ast EcoString, type_: &'ast Arc, ) { visit_typed_pattern_discard(self, location, name, type_); } fn visit_typed_pattern_list( &mut self, location: &'ast SrcSpan, elements: &'ast Vec, tail: &'ast Option>, type_: &'ast Arc, ) { visit_typed_pattern_list(self, location, elements, tail, type_); } #[allow(clippy::too_many_arguments)] fn visit_typed_pattern_constructor( &mut self, location: &'ast SrcSpan, name_location: &'ast SrcSpan, name: &'ast EcoString, arguments: &'ast Vec>, module: &'ast Option<(EcoString, SrcSpan)>, constructor: &'ast Inferred, spread: &'ast Option, type_: &'ast Arc, ) { visit_typed_pattern_constructor( self, location, name_location, name, arguments, module, constructor, spread, type_, ); } fn visit_typed_pattern_call_arg(&mut self, arg: &'ast CallArg) { visit_typed_pattern_call_arg(self, arg); } fn visit_typed_pattern_tuple( &mut self, location: &'ast SrcSpan, elements: &'ast Vec, ) { visit_typed_pattern_tuple(self, location, elements); } fn visit_typed_pattern_bit_array( &mut self, location: &'ast SrcSpan, segments: &'ast [TypedPatternBitArraySegment], ) { visit_typed_pattern_bit_array(self, location, segments); } fn visit_typed_pattern_bit_array_option(&mut self, option: &'ast BitArrayOption) { visit_typed_pattern_bit_array_option(self, option); } fn visit_typed_pattern_string_prefix( &mut self, location: &'ast SrcSpan, left_location: &'ast SrcSpan, left_side_assignment: &'ast Option<(EcoString, SrcSpan)>, right_location: &'ast SrcSpan, left_side_string: &'ast EcoString, right_side_assignment: &'ast AssignName, ) { visit_typed_pattern_string_prefix( self, location, left_location, left_side_assignment, right_location, left_side_string, right_side_assignment, ); } fn visit_typed_pattern_invalid(&mut self, location: &'ast SrcSpan, type_: &'ast Arc) { visit_typed_pattern_invalid(self, location, type_); } fn visit_type_ast( &mut self, node: &'ast TypeAst, // The type inferred for this annotation. // It might not always be possible to infer one in presence of type // errors, so this is optional! inferred_type: Option>, ) { visit_type_ast(self, node, inferred_type); } fn visit_type_ast_constructor( &mut self, location: &'ast SrcSpan, name: &'ast TypeAstConstructorName, arguments: &'ast [TypeAst], inferred_arguments_types: Option>>, ) { visit_type_ast_constructor(self, location, name, arguments, inferred_arguments_types); } fn visit_type_ast_fn( &mut self, location: &'ast SrcSpan, arguments: &'ast [TypeAst], arguments_types: Option>>, return_: &'ast TypeAst, return_type: Option>, ) { visit_type_ast_fn( self, location, arguments, arguments_types, return_, return_type, ); } fn visit_type_ast_var(&mut self, location: &'ast SrcSpan, name: &'ast EcoString) { visit_type_ast_var(self, location, name); } fn visit_type_ast_tuple( &mut self, location: &'ast SrcSpan, elements: &'ast [TypeAst], elements_types: Option<&Vec>>, ) { visit_type_ast_tuple(self, location, elements, elements_types); } fn visit_type_ast_hole( &mut self, location: &'ast SrcSpan, name: &'ast EcoString, type_: Option>, ) { visit_type_ast_hole(self, location, name, type_); } fn visit_typed_constant(&mut self, constant: &'ast TypedConstant) { visit_typed_constant(self, constant); } fn visit_typed_constant_todo( &mut self, location: &'ast SrcSpan, type_: &'ast Arc, message: &'ast Option>, ) { visit_typed_constant_todo(self, location, type_, message); } fn visit_typed_constant_int( &mut self, location: &'ast SrcSpan, value: &'ast EcoString, int_value: &'ast BigInt, ) { visit_typed_constant_int(self, location, value, int_value); } fn visit_typed_constant_float( &mut self, location: &'ast SrcSpan, value: &'ast EcoString, float_value: &'ast LiteralFloatValue, ) { visit_typed_constant_float(self, location, value, float_value); } fn visit_typed_constant_string(&mut self, location: &'ast SrcSpan, value: &'ast EcoString) { visit_typed_constant_string(self, location, value); } fn visit_typed_constant_tuple( &mut self, location: &'ast SrcSpan, elements: &'ast Vec, type_: &'ast Arc, ) { visit_typed_constant_tuple(self, location, elements, type_); } fn visit_typed_constant_list( &mut self, location: &'ast SrcSpan, elements: &'ast Vec, type_: &'ast Arc, tail: &'ast Option>, ) { visit_typed_constant_list(self, location, elements, type_, tail); } #[allow(clippy::too_many_arguments)] fn visit_typed_constant_record( &mut self, location: &'ast SrcSpan, module: &'ast Option<(EcoString, SrcSpan)>, name: &'ast EcoString, arguments: &'ast Option>>, type_: &'ast Arc, field_map: &'ast Inferred, record_constructor: &'ast Option>, ) { visit_typed_constant_record( self, location, module, name, arguments, type_, field_map, record_constructor, ); } #[allow(clippy::too_many_arguments)] fn visit_typed_constant_record_update( &mut self, location: &'ast SrcSpan, constructor_location: &'ast SrcSpan, module: &'ast Option<(EcoString, SrcSpan)>, name: &'ast EcoString, record: &'ast RecordBeingUpdated, arguments: &'ast [RecordUpdateArg], type_: &'ast Arc, field_map: &'ast Inferred, ) { visit_typed_constant_record_update( self, location, constructor_location, module, name, record, arguments, type_, field_map, ); } fn visit_typed_constant_bit_array( &mut self, location: &'ast SrcSpan, segments: &'ast [TypedConstantBitArraySegment], ) { visit_typed_constant_bit_array(self, location, segments); } fn visit_typed_constant_var( &mut self, location: &'ast SrcSpan, module: &'ast Option<(EcoString, SrcSpan)>, name: &'ast EcoString, constructor: &'ast Option>, type_: &'ast Arc, ) { visit_typed_constant_var(self, location, module, name, constructor, type_); } fn visit_typed_constant_string_concatenation( &mut self, location: &'ast SrcSpan, left: &'ast TypedConstant, right: &'ast TypedConstant, ) { visit_typed_constant_string_concatenation(self, location, left, right); } fn visit_typed_constant_invalid( &mut self, location: &'ast SrcSpan, type_: &'ast Arc, extra_information: &'ast Option, ) { visit_typed_constant_invalid(self, location, type_, extra_information); } } fn visit_typed_constant_invalid<'a, V: Visit<'a> + ?Sized>( _v: &mut V, _location: &'a SrcSpan, _type_: &'a Type, _extra_information: &'a Option, ) { // No further traversal needed for constant invalid expressions } fn visit_typed_constant_string_concatenation<'a, V: Visit<'a> + ?Sized>( v: &mut V, _location: &'a SrcSpan, left: &'a TypedConstant, right: &'a TypedConstant, ) { v.visit_typed_constant(left); v.visit_typed_constant(right); } pub fn visit_typed_constant_var<'a, V: Visit<'a> + ?Sized>( _v: &mut V, _location: &'a SrcSpan, _module: &'a Option<(EcoString, SrcSpan)>, _name: &'a EcoString, _constructor: &'a Option>, _type_: &'a Arc, ) { // No further traversal needed for constant vars } fn visit_typed_constant_bit_array<'a, V: Visit<'a> + ?Sized>( _v: &mut V, _location: &'a SrcSpan, _segments: &'a [TypedConstantBitArraySegment], ) { // TODO } #[allow(clippy::too_many_arguments)] pub fn visit_typed_constant_record<'a, V: Visit<'a> + ?Sized>( v: &mut V, _location: &'a SrcSpan, _module: &'a Option<(EcoString, SrcSpan)>, _name: &'a EcoString, arguments: &'a Option>>, _type_: &'a Arc, _field_map: &'a Inferred, _record_constructor: &'a Option>, ) { for argument in arguments.iter().flatten() { v.visit_typed_constant(&argument.value); } } #[allow(clippy::too_many_arguments)] pub fn visit_typed_constant_record_update<'a, V: Visit<'a> + ?Sized>( v: &mut V, _location: &'a SrcSpan, _constructor_location: &'a SrcSpan, _module: &'a Option<(EcoString, SrcSpan)>, _name: &'a EcoString, record: &'a RecordBeingUpdated, arguments: &'a [RecordUpdateArg], _type_: &'a Arc, _field_map: &'a Inferred, ) { v.visit_typed_constant(&record.base); for argument in arguments { v.visit_typed_constant(&argument.value); } } fn visit_typed_constant_list<'a, V: Visit<'a> + ?Sized>( v: &mut V, _location: &'a SrcSpan, elements: &'a Vec, _type_: &'a Arc, tail: &'a Option>, ) { for element in elements { v.visit_typed_constant(element); } if let Some(tail) = tail { v.visit_typed_constant(tail); } } fn visit_typed_constant_tuple<'a, V: Visit<'a> + ?Sized>( v: &mut V, _location: &'a SrcSpan, elements: &'a Vec, _type_: &'a Arc, ) { for element in elements { v.visit_typed_constant(element); } } fn visit_typed_constant_string<'a, V: Visit<'a> + ?Sized>( _v: &mut V, _location: &'a SrcSpan, _value: &'a EcoString, ) { // No further traversal needed for constant strings } fn visit_typed_constant_float<'a, V: Visit<'a> + ?Sized>( _v: &mut V, _location: &'a SrcSpan, _value: &'a EcoString, _float_value: &'a LiteralFloatValue, ) { // No further traversal needed for constant floats } fn visit_typed_constant_int<'a, V: Visit<'a> + ?Sized>( _v: &mut V, _location: &'a SrcSpan, _value: &'a EcoString, _int_value: &'a BigInt, ) { // No further traversal needed for constant ints } pub fn visit_typed_constant_todo<'a, V: Visit<'a> + ?Sized>( _v: &mut V, _location: &'a SrcSpan, _type_: &'a Arc, _message: &'a Option>, ) { // No further traversal needed for constant todos } pub fn visit_typed_module<'a, V>(v: &mut V, module: &'a TypedModule) where V: Visit<'a> + ?Sized, { let TypedDefinitions { imports, constants, custom_types, type_aliases, functions, } = &module.definitions; for import in imports { v.visit_typed_import(import); } for constant in constants { v.visit_typed_module_constant(constant); } for custom_type in custom_types { v.visit_typed_custom_type(custom_type); } for type_alias in type_aliases { v.visit_typed_type_alias(type_alias); } for function in functions { v.visit_typed_function(function); } } pub fn visit_typed_function<'a, V>(v: &mut V, fun: &'a TypedFunction) where V: Visit<'a> + ?Sized, { for argument in fun.arguments.iter() { if let Some(annotation) = &argument.annotation { v.visit_type_ast(annotation, Some(argument.type_.clone())); } } if let Some(annotation) = &fun.return_annotation { v.visit_type_ast(annotation, Some(fun.return_type.clone())); } for statement in &fun.body { v.visit_typed_statement(statement); } } pub fn visit_type_ast<'a, V>(v: &mut V, node: &'a TypeAst, type_: Option>) where V: Visit<'a> + ?Sized, { match node { TypeAst::Constructor(super::TypeAstConstructor { location, arguments, name, start_parentheses: _, }) => { v.visit_type_ast_constructor( location, name, arguments, type_.and_then(|type_| type_.constructor_types()), ); } TypeAst::Fn(super::TypeAstFn { location, arguments, return_, }) => { let (arguments_types, return_type) = match type_.and_then(|type_| type_.fn_types()) { Some((arguments_types, return_type)) => (Some(arguments_types), Some(return_type)), None => (None, None), }; v.visit_type_ast_fn(location, arguments, arguments_types, return_, return_type); } TypeAst::Var(super::TypeAstVar { location, name }) => { v.visit_type_ast_var(location, name); } TypeAst::Tuple(super::TypeAstTuple { location, elements }) => { let elements_types = if let Some(Type::Tuple { elements }) = type_.as_deref() { Some(elements) } else { None }; v.visit_type_ast_tuple(location, elements, elements_types); } TypeAst::Hole(super::TypeAstHole { location, name }) => { v.visit_type_ast_hole(location, name, type_); } } } pub fn visit_type_ast_constructor<'a, V>( v: &mut V, _location: &'a SrcSpan, _name: &'a TypeAstConstructorName, arguments: &'a [TypeAst], inferred_arguments_types: Option>>, ) where V: Visit<'a> + ?Sized, { for (i, argument) in arguments.iter().enumerate() { let argument_type = inferred_arguments_types .as_ref() .and_then(|types| types.get(i)); v.visit_type_ast(argument, argument_type.cloned()); } } pub fn visit_type_ast_fn<'a, V>( v: &mut V, _location: &'a SrcSpan, arguments: &'a [TypeAst], arguments_types: Option>>, return_: &'a TypeAst, return_type: Option>, ) where V: Visit<'a> + ?Sized, { for (i, argument) in arguments.iter().enumerate() { v.visit_type_ast( argument, arguments_types .as_ref() .and_then(|types| types.get(i)) .cloned(), ); } v.visit_type_ast(return_, return_type); } pub fn visit_type_ast_var<'a, V>(_v: &mut V, _location: &'a SrcSpan, _name: &'a EcoString) where V: Visit<'a> + ?Sized, { // No further traversal needed for variables } pub fn visit_type_ast_tuple<'a, V>( v: &mut V, _location: &'a SrcSpan, elements: &'a [TypeAst], elements_types: Option<&Vec>>, ) where V: Visit<'a> + ?Sized, { for (i, element) in elements.iter().enumerate() { let element_type = elements_types .as_ref() .and_then(|types| types.get(i)) .cloned(); v.visit_type_ast(element, element_type); } } pub fn visit_type_ast_hole<'a, V>( _v: &mut V, _location: &'a SrcSpan, _name: &'a EcoString, _type_: Option>, ) where V: Visit<'a> + ?Sized, { // No further traversal needed for holes } pub fn visit_typed_module_constant<'a, V>(v: &mut V, constant: &'a TypedModuleConstant) where V: Visit<'a> + ?Sized, { if let Some(annotation) = &constant.annotation { v.visit_type_ast(annotation, Some(constant.type_.clone())); } v.visit_typed_constant(&constant.value); } pub fn visit_typed_constant<'a, V: Visit<'a> + ?Sized>(v: &mut V, constant: &'a TypedConstant) { match constant { super::Constant::Todo { location, type_, message, } => v.visit_typed_constant_todo(location, type_, message), super::Constant::Int { location, value, int_value, } => v.visit_typed_constant_int(location, value, int_value), super::Constant::Float { location, value, float_value, } => v.visit_typed_constant_float(location, value, float_value), super::Constant::String { location, value } => { v.visit_typed_constant_string(location, value); } super::Constant::Tuple { location, elements, type_, } => v.visit_typed_constant_tuple(location, elements, type_), super::Constant::List { location, elements, type_, tail, } => v.visit_typed_constant_list(location, elements, type_, tail), super::Constant::Record { location, module, name, arguments, type_, field_map, record_constructor, } => v.visit_typed_constant_record( location, module, name, arguments, type_, field_map, record_constructor, ), super::Constant::RecordUpdate { location, constructor_location, module, name, record, arguments, type_, field_map, } => v.visit_typed_constant_record_update( location, constructor_location, module, name, record, arguments, type_, field_map, ), super::Constant::BitArray { location, segments } => { v.visit_typed_constant_bit_array(location, segments); } super::Constant::Var { location, module, name, constructor, type_, } => v.visit_typed_constant_var(location, module, name, constructor, type_), super::Constant::StringConcatenation { location, left, right, } => v.visit_typed_constant_string_concatenation(location, left, right), super::Constant::Invalid { location, type_, extra_information, } => v.visit_typed_constant_invalid(location, type_, extra_information), } } pub fn visit_typed_custom_type<'a, V>(v: &mut V, custom_type: &'a TypedCustomType) where V: Visit<'a> + ?Sized, { for record in &custom_type.constructors { for argument in &record.arguments { v.visit_type_ast(&argument.ast, Some(argument.type_.clone())); } } } pub fn visit_typed_type_alias<'a, V>(v: &mut V, type_alias: &'a TypedTypeAlias) where V: Visit<'a> + ?Sized, { v.visit_type_ast(&type_alias.type_ast, Some(type_alias.type_.clone())); } pub fn visit_typed_import<'a, V>(_v: &mut V, _import: &'a TypedImport) where V: Visit<'a> + ?Sized, { } pub fn visit_typed_expr<'a, V>(v: &mut V, node: &'a TypedExpr) where V: Visit<'a> + ?Sized, { match node { TypedExpr::Int { location, type_, value, int_value, } => v.visit_typed_expr_int(location, type_, value, int_value), TypedExpr::Float { location, type_, value, float_value: _, } => v.visit_typed_expr_float(location, type_, value), TypedExpr::String { location, type_, value, } => v.visit_typed_expr_string(location, type_, value), TypedExpr::Block { location, statements, } => v.visit_typed_expr_block(location, statements), TypedExpr::Pipeline { location, first_value, assignments, finally, finally_kind, } => v.visit_typed_expr_pipeline(location, first_value, assignments, finally, finally_kind), TypedExpr::Var { location, constructor, name, } => v.visit_typed_expr_var(location, constructor, name), TypedExpr::Fn { location, type_, kind, arguments, body, return_annotation, purity: _, } => v.visit_typed_expr_fn(location, type_, kind, arguments, body, return_annotation), TypedExpr::List { location, type_, elements, tail, } => v.visit_typed_expr_list(location, type_, elements, tail), TypedExpr::Call { location, type_, fun, arguments, open_parenthesis, } => v.visit_typed_expr_call(location, type_, fun, arguments, open_parenthesis), TypedExpr::BinOp { location, type_, operator, operator_start, left, right, } => v.visit_typed_expr_bin_op(location, type_, operator, operator_start, left, right), TypedExpr::Case { location, type_, subjects, clauses, compiled_case, } => v.visit_typed_expr_case(location, type_, subjects, clauses, compiled_case), TypedExpr::RecordAccess { location, field_start, type_, label, index, record, documentation, } => v.visit_typed_expr_record_access( location, field_start, type_, label, index, record, documentation, ), TypedExpr::ModuleSelect { location, field_start, type_, label, module_name, module_alias, constructor, } => v.visit_typed_expr_module_select( location, field_start, type_, label, module_name, module_alias, constructor, ), TypedExpr::Tuple { location, type_, elements, } => v.visit_typed_expr_tuple(location, type_, elements), TypedExpr::TupleIndex { location, type_, index, tuple, } => v.visit_typed_expr_tuple_index(location, type_, index, tuple), TypedExpr::Todo { location, message, kind, type_, } => v.visit_typed_expr_todo(location, message, kind, type_), TypedExpr::Panic { location, message, type_, } => v.visit_typed_expr_panic(location, message, type_), TypedExpr::BitArray { location, type_, segments, } => v.visit_typed_expr_bit_array(location, type_, segments), TypedExpr::RecordUpdate { location, spread_start, type_, updated_record, updated_record_assigned_name, constructor, arguments, } => v.visit_typed_expr_record_update( location, spread_start, type_, updated_record, updated_record_assigned_name, constructor, arguments, ), TypedExpr::NegateBool { location, value } => { v.visit_typed_expr_negate_bool(location, value); } TypedExpr::NegateInt { location, value } => v.visit_typed_expr_negate_int(location, value), TypedExpr::Invalid { location, type_, extra_information, } => v.visit_typed_expr_invalid(location, type_, extra_information), TypedExpr::Echo { location, expression, message, type_, } => v.visit_typed_expr_echo(location, type_, expression, message), TypedExpr::PositionalAccess { .. } => {} } } pub fn visit_typed_expr_int<'a, V>( _v: &mut V, _location: &'a SrcSpan, _type_: &'a Arc, _string_value: &'a EcoString, _int_value: &'a BigInt, ) where V: Visit<'a> + ?Sized, { } pub fn visit_typed_expr_float<'a, V>( _v: &mut V, _location: &'a SrcSpan, _type_: &'a Arc, _value: &'a EcoString, ) where V: Visit<'a> + ?Sized, { } pub fn visit_typed_expr_string<'a, V>( _v: &mut V, _location: &'a SrcSpan, _type_: &'a Arc, _value: &'a EcoString, ) where V: Visit<'a> + ?Sized, { } pub fn visit_typed_expr_block<'a, V>( v: &mut V, _location: &'a SrcSpan, statements: &'a [TypedStatement], ) where V: Visit<'a> + ?Sized, { for statement in statements { v.visit_typed_statement(statement); } } pub fn visit_typed_expr_pipeline<'a, V>( v: &mut V, _location: &'a SrcSpan, first_value: &'a TypedPipelineAssignment, assignments: &'a [(TypedPipelineAssignment, PipelineAssignmentKind)], finally: &'a TypedExpr, _finally_kind: &'a PipelineAssignmentKind, ) where V: Visit<'a> + ?Sized, { v.visit_typed_pipeline_assignment(first_value); for (assignment, _kind) in assignments { v.visit_typed_pipeline_assignment(assignment); } v.visit_typed_expr(finally); } pub fn visit_typed_pipeline_assignment<'a, V>(v: &mut V, assignment: &'a TypedPipelineAssignment) where V: Visit<'a> + ?Sized, { v.visit_typed_expr(&assignment.value); } pub fn visit_typed_expr_var<'a, V>( _v: &mut V, _location: &'a SrcSpan, _constructor: &'a ValueConstructor, _name: &'a EcoString, ) where V: Visit<'a> + ?Sized, { /* TODO */ } pub fn visit_typed_expr_fn<'a, V>( v: &mut V, _location: &'a SrcSpan, type_: &'a Arc, _kind: &'a FunctionLiteralKind, arguments: &'a [TypedArg], body: &'a Vec1, return_annotation: &'a Option, ) where V: Visit<'a> + ?Sized, { for argument in arguments { if let Some(annotation) = &argument.annotation { v.visit_type_ast(annotation, Some(argument.type_.clone())); } } if let Some(return_) = return_annotation { v.visit_type_ast(return_, type_.fn_types().map(|(_, return_)| return_)); } for statement in body { v.visit_typed_statement(statement); } } pub fn visit_typed_expr_list<'a, V>( v: &mut V, _location: &'a SrcSpan, _type_: &'a Arc, elements: &'a [TypedExpr], tail: &'a Option>, ) where V: Visit<'a> + ?Sized, { for element in elements { v.visit_typed_expr(element); } if let Some(tail) = tail { v.visit_typed_expr(tail); } } pub fn visit_typed_expr_call<'a, V>( v: &mut V, _location: &'a SrcSpan, _type_: &'a Arc, fun: &'a TypedExpr, arguments: &'a [TypedCallArg], _arguments_start: &'a Option, ) where V: Visit<'a> + ?Sized, { v.visit_typed_expr(fun); for argument in arguments { v.visit_typed_call_arg(argument); } } pub fn visit_typed_expr_bin_op<'a, V>( v: &mut V, _location: &'a SrcSpan, _type_: &'a Arc, _operator: &'a BinOp, _operator_start: &'a u32, left: &'a TypedExpr, right: &'a TypedExpr, ) where V: Visit<'a> + ?Sized, { v.visit_typed_expr(left); v.visit_typed_expr(right); } pub fn visit_typed_expr_case<'a, V>( v: &mut V, _location: &'a SrcSpan, _type_: &'a Arc, subjects: &'a [TypedExpr], clauses: &'a [TypedClause], _compiled_case: &'a CompiledCase, ) where V: Visit<'a> + ?Sized, { for subject in subjects { v.visit_typed_expr(subject); } for clause in clauses { v.visit_typed_clause(clause); } } #[allow(clippy::too_many_arguments)] pub fn visit_typed_expr_record_access<'a, V>( v: &mut V, _location: &'a SrcSpan, _field_start: &'a u32, _type_: &'a Arc, _label: &'a EcoString, _index: &'a u64, record: &'a TypedExpr, _documentation: &'a Option, ) where V: Visit<'a> + ?Sized, { v.visit_typed_expr(record); } #[allow(clippy::too_many_arguments)] pub fn visit_typed_expr_module_select<'a, V>( _v: &mut V, _location: &'a SrcSpan, _field_start: &'a u32, _type_: &'a Arc, _label: &'a EcoString, _module_name: &'a EcoString, _module_alias: &'a EcoString, _constructor: &'a ModuleValueConstructor, ) where V: Visit<'a> + ?Sized, { /* TODO */ } pub fn visit_typed_expr_tuple<'a, V>( v: &mut V, _location: &'a SrcSpan, _type_: &'a Arc, elements: &'a [TypedExpr], ) where V: Visit<'a> + ?Sized, { for element in elements { v.visit_typed_expr(element); } } pub fn visit_typed_expr_tuple_index<'a, V>( v: &mut V, _location: &'a SrcSpan, _type_: &'a Arc, _index: &'a u64, tuple: &'a TypedExpr, ) where V: Visit<'a> + ?Sized, { v.visit_typed_expr(tuple); } pub fn visit_typed_expr_todo<'a, V>( v: &mut V, _location: &'a SrcSpan, message: &'a Option>, _kind: &'a TodoKind, _type_: &'a Arc, ) where V: Visit<'a> + ?Sized, { if let Some(message) = message { v.visit_typed_expr(message); } } pub fn visit_typed_expr_echo<'a, V>( v: &mut V, _location: &'a SrcSpan, _type_: &'a Arc, expression: &'a Option>, message: &'a Option>, ) where V: Visit<'a> + ?Sized, { if let Some(expression) = expression { v.visit_typed_expr(expression); } if let Some(message) = message { v.visit_typed_expr(message); } } pub fn visit_typed_expr_panic<'a, V>( v: &mut V, _location: &'a SrcSpan, message: &'a Option>, _type_: &'a Arc, ) where V: Visit<'a> + ?Sized, { if let Some(message) = message { v.visit_typed_expr(message); } } pub fn visit_typed_expr_bit_array<'a, V>( v: &mut V, _location: &'a SrcSpan, _type_: &'a Arc, segments: &'a [TypedExprBitArraySegment], ) where V: Visit<'a> + ?Sized, { for segment in segments { v.visit_typed_expr_bit_array_segment(segment); } } #[allow(clippy::too_many_arguments)] pub fn visit_typed_expr_record_update<'a, V>( v: &mut V, _location: &'a SrcSpan, _spread_start: &'a u32, _type_: &'a Arc, updated_record: &'a TypedExpr, _updated_record_assigned_name: &'a Option, constructor: &'a TypedExpr, arguments: &'a [TypedCallArg], ) where V: Visit<'a> + ?Sized, { v.visit_typed_expr(constructor); v.visit_typed_expr(updated_record); for argument in arguments { v.visit_typed_call_arg(argument); } } pub fn visit_typed_expr_negate_bool<'a, V>(v: &mut V, _location: &'a SrcSpan, value: &'a TypedExpr) where V: Visit<'a> + ?Sized, { v.visit_typed_expr(value); } pub fn visit_typed_expr_negate_int<'a, V>(v: &mut V, _location: &'a SrcSpan, value: &'a TypedExpr) where V: Visit<'a> + ?Sized, { v.visit_typed_expr(value); } pub fn visit_typed_statement<'a, V>(v: &mut V, statement: &'a TypedStatement) where V: Visit<'a> + ?Sized, { match statement { Statement::Expression(expression) => v.visit_typed_expr(expression), Statement::Assignment(assignment) => v.visit_typed_assignment(assignment), Statement::Use(use_) => v.visit_typed_use(use_), Statement::Assert(assert) => v.visit_typed_assert(assert), } } pub fn visit_typed_assignment<'a, V>(v: &mut V, assignment: &'a TypedAssignment) where V: Visit<'a> + ?Sized, { if let Some(annotation) = &assignment.annotation { v.visit_type_ast(annotation, Some(assignment.type_())); } v.visit_typed_expr(&assignment.value); v.visit_typed_pattern(&assignment.pattern); } pub fn visit_typed_use<'a, V>(v: &mut V, use_: &'a TypedUse) where V: Visit<'a> + ?Sized, { v.visit_typed_expr(&use_.call); // TODO: We should also visit the typed patterns!! } pub fn visit_typed_assert<'a, V>(v: &mut V, assert: &'a TypedAssert) where V: Visit<'a> + ?Sized, { v.visit_typed_expr(&assert.value); if let Some(message) = &assert.message { v.visit_typed_expr(message); } } pub fn visit_typed_call_arg<'a, V>(v: &mut V, arg: &'a TypedCallArg) where V: Visit<'a> + ?Sized, { v.visit_typed_expr(&arg.value); } pub fn visit_typed_clause<'a, V>(v: &mut V, clause: &'a TypedClause) where V: Visit<'a> + ?Sized, { for pattern in clause.pattern.iter() { v.visit_typed_pattern(pattern); } for patterns in clause.alternative_patterns.iter() { for pattern in patterns { v.visit_typed_pattern(pattern); } } if let Some(guard) = &clause.guard { v.visit_typed_clause_guard(guard); } v.visit_typed_expr(&clause.then); } pub fn visit_typed_clause_guard<'a, V>(v: &mut V, guard: &'a TypedClauseGuard) where V: Visit<'a> + ?Sized, { match guard { super::ClauseGuard::BinaryOperator { left, right, location, operator, operator_start, } => v.visit_typed_clause_guard_bin_op(left, right, operator, operator_start, location), super::ClauseGuard::Block { location: _, value } => v.visit_typed_clause_guard(value), super::ClauseGuard::Not { location: _, expression, } => v.visit_typed_clause_guard(expression), super::ClauseGuard::Var { location, type_, name, definition_location, origin, } => v.visit_typed_clause_guard_var(location, name, type_, definition_location, origin), super::ClauseGuard::TupleIndex { location, index, type_, tuple, } => v.visit_typed_clause_guard_tuple_index(location, index, type_, tuple), super::ClauseGuard::FieldAccess { label_location, index, label, type_, container, } => { v.visit_typed_clause_guard_field_access(label_location, index, label, type_, container); } super::ClauseGuard::ModuleSelect { location, field_start, definition_location, type_, label, module_name, module_alias, literal, } => v.visit_typed_clause_guard_module_select( location, field_start, definition_location, type_, label, module_name, module_alias, literal, ), super::ClauseGuard::Constant(constant) => v.visit_typed_constant(constant), super::ClauseGuard::Invalid { .. } => (), } } pub fn visit_typed_clause_guard_bin_op<'a, V>( v: &mut V, left: &'a TypedClauseGuard, right: &'a TypedClauseGuard, _operator: &'a BinOp, _operator_start: &'a u32, _location: &'a SrcSpan, ) where V: Visit<'a> + ?Sized, { v.visit_typed_clause_guard(left); v.visit_typed_clause_guard(right); } pub fn visit_typed_clause_guard_var<'a, V>( _v: &mut V, _location: &'a SrcSpan, _name: &'a EcoString, _type_: &'a Arc, _definition_location: &'a SrcSpan, _origin: &'a VariableOrigin, ) where V: Visit<'a> + ?Sized, { } pub fn visit_typed_clause_guard_tuple_index<'a, V>( v: &mut V, _location: &'a SrcSpan, _index: &'a u64, _type_: &'a Arc, tuple: &'a TypedClauseGuard, ) where V: Visit<'a> + ?Sized, { v.visit_typed_clause_guard(tuple); } pub fn visit_typed_clause_guard_field_access<'a, V>( v: &mut V, _label_location: &'a SrcSpan, _index: &'a Option, _label: &'a EcoString, _type_: &'a Arc, container: &'a TypedClauseGuard, ) where V: Visit<'a> + ?Sized, { v.visit_typed_clause_guard(container); } #[allow(clippy::too_many_arguments)] pub fn visit_typed_clause_guard_module_select<'a, V>( _v: &mut V, _location: &'a SrcSpan, _field_start: &'a u32, _definition_location: &'a SrcSpan, _type_: &'a Arc, _label: &'a EcoString, _module_name: &'a EcoString, _module_alias: &'a EcoString, _literal: &'a TypedConstant, ) where V: Visit<'a> + ?Sized, { } pub fn visit_typed_expr_bit_array_segment<'a, V>(v: &mut V, segment: &'a TypedExprBitArraySegment) where V: Visit<'a> + ?Sized, { v.visit_typed_expr(&segment.value); for option in &segment.options { v.visit_typed_bit_array_option(option); } } pub fn visit_typed_bit_array_option<'a, V>(v: &mut V, option: &'a BitArrayOption) where V: Visit<'a> + ?Sized, { match option { BitArrayOption::Bytes { location: _ } => { /* TODO */ } BitArrayOption::Int { location: _ } => { /* TODO */ } BitArrayOption::Float { location: _ } => { /* TODO */ } BitArrayOption::Bits { location: _ } => { /* TODO */ } BitArrayOption::Utf8 { location: _ } => { /* TODO */ } BitArrayOption::Utf16 { location: _ } => { /* TODO */ } BitArrayOption::Utf32 { location: _ } => { /* TODO */ } BitArrayOption::Utf8Codepoint { location: _ } => { /* TODO */ } BitArrayOption::Utf16Codepoint { location: _ } => { /* TODO */ } BitArrayOption::Utf32Codepoint { location: _ } => { /* TODO */ } BitArrayOption::Signed { location: _ } => { /* TODO */ } BitArrayOption::Unsigned { location: _ } => { /* TODO */ } BitArrayOption::Big { location: _ } => { /* TODO */ } BitArrayOption::Little { location: _ } => { /* TODO */ } BitArrayOption::Native { location: _ } => { /* TODO */ } BitArrayOption::Size { location: _, value, short_form: _, } => { v.visit_typed_expr(value); } BitArrayOption::Unit { location: _, value: _, } => { /* TODO */ } } } pub fn visit_typed_pattern<'a, V>(v: &mut V, pattern: &'a TypedPattern) where V: Visit<'a> + ?Sized, { match pattern { Pattern::Int { location, value, int_value: _, } => v.visit_typed_pattern_int(location, value), Pattern::Float { location, value, float_value: _, } => v.visit_typed_pattern_float(location, value), Pattern::String { location, value } => v.visit_typed_pattern_string(location, value), Pattern::Variable { location, name, type_, origin, } => v.visit_typed_pattern_variable(location, name, type_, origin), Pattern::BitArraySize(size) => v.visit_typed_pattern_bit_array_size(size), Pattern::Assign { location, name, pattern, } => v.visit_typed_pattern_assign(location, name, pattern), Pattern::Discard { location, name, type_, } => v.visit_typed_pattern_discard(location, name, type_), Pattern::List { location, elements, tail, type_, } => v.visit_typed_pattern_list(location, elements, tail, type_), Pattern::Constructor { location, name_location, name, arguments, module, constructor, spread, type_, } => v.visit_typed_pattern_constructor( location, name_location, name, arguments, module, constructor, spread, type_, ), Pattern::Tuple { location, elements } => v.visit_typed_pattern_tuple(location, elements), Pattern::BitArray { location, segments } => { v.visit_typed_pattern_bit_array(location, segments); } Pattern::StringPrefix { location, left_location, left_side_assignment, right_location, left_side_string, right_side_assignment, } => v.visit_typed_pattern_string_prefix( location, left_location, left_side_assignment, right_location, left_side_string, right_side_assignment, ), Pattern::Invalid { location, type_ } => v.visit_typed_pattern_invalid(location, type_), } } fn visit_typed_pattern_int<'a, V>(_v: &mut V, _location: &'a SrcSpan, _value: &'a EcoString) where V: Visit<'a> + ?Sized, { } pub fn visit_typed_pattern_float<'a, V>(_v: &mut V, _location: &'a SrcSpan, _value: &'a EcoString) where V: Visit<'a> + ?Sized, { } pub fn visit_typed_pattern_string<'a, V>(_v: &mut V, _location: &'a SrcSpan, _value: &'a EcoString) where V: Visit<'a> + ?Sized, { } pub fn visit_typed_pattern_variable<'a, V>( _v: &mut V, _location: &'a SrcSpan, _name: &'a EcoString, _type_: &'a Arc, _origin: &'a VariableOrigin, ) where V: Visit<'a> + ?Sized, { } pub fn visit_typed_pattern_bit_array_size<'a, V>(v: &mut V, size: &'a TypedBitArraySize) where V: Visit<'a> + ?Sized, { match size { BitArraySize::Int { location, value, int_value: _, } => v.visit_typed_bit_array_size_int(location, value), BitArraySize::Variable { location, name, constructor, type_, } => v.visit_typed_bit_array_size_variable(location, name, constructor, type_), BitArraySize::BinaryOperator { left, right, .. } => { v.visit_typed_pattern_bit_array_size(left); v.visit_typed_pattern_bit_array_size(right); } BitArraySize::Block { inner, .. } => v.visit_typed_pattern_bit_array_size(inner), } } pub fn visit_typed_bit_array_size_int<'a, V>( _v: &mut V, _location: &'a SrcSpan, _value: &'a EcoString, ) where V: Visit<'a> + ?Sized, { } pub fn visit_typed_bit_array_size_variable<'a, V>( _v: &mut V, _location: &'a SrcSpan, _name: &'a EcoString, _constructor: &'a Option>, _type_: &'a Arc, ) where V: Visit<'a> + ?Sized, { } pub fn visit_typed_pattern_assign<'a, V>( v: &mut V, _location: &'a SrcSpan, _name: &'a EcoString, pattern: &'a TypedPattern, ) where V: Visit<'a> + ?Sized, { v.visit_typed_pattern(pattern); } pub fn visit_typed_pattern_discard<'a, V>( _v: &mut V, _location: &'a SrcSpan, _name: &'a EcoString, _type_: &'a Arc, ) where V: Visit<'a> + ?Sized, { } pub fn visit_typed_pattern_list<'a, V>( v: &mut V, _location: &'a SrcSpan, elements: &'a Vec, tail: &'a Option>, _type_: &'a Arc, ) where V: Visit<'a> + ?Sized, { for element in elements { v.visit_typed_pattern(element); } if let Some(tail) = tail { v.visit_typed_pattern(&tail.pattern); } } #[allow(clippy::too_many_arguments)] pub fn visit_typed_pattern_constructor<'a, V>( v: &mut V, _location: &'a SrcSpan, _name_location: &'a SrcSpan, _name: &'a EcoString, arguments: &'a Vec>, _module: &'a Option<(EcoString, SrcSpan)>, _constructor: &'a Inferred, _spread: &'a Option, _type_: &'a Arc, ) where V: Visit<'a> + ?Sized, { for argument in arguments { v.visit_typed_pattern_call_arg(argument); } } pub fn visit_typed_pattern_call_arg<'a, V>(v: &mut V, argument: &'a CallArg) where V: Visit<'a> + ?Sized, { v.visit_typed_pattern(&argument.value); } pub fn visit_typed_pattern_tuple<'a, V>( v: &mut V, _location: &'a SrcSpan, elements: &'a Vec, ) where V: Visit<'a> + ?Sized, { for element in elements { v.visit_typed_pattern(element); } } pub fn visit_typed_pattern_bit_array<'a, V>( v: &mut V, _location: &'a SrcSpan, segments: &'a [TypedPatternBitArraySegment], ) where V: Visit<'a> + ?Sized, { for segment in segments { v.visit_typed_pattern(&segment.value); for option in segment.options.iter() { v.visit_typed_pattern_bit_array_option(option); } } } pub fn visit_typed_pattern_bit_array_option<'a, V>( v: &mut V, option: &'a BitArrayOption, ) where V: Visit<'a> + ?Sized, { match option { BitArrayOption::Bytes { location: _ } => { /* TODO */ } BitArrayOption::Int { location: _ } => { /* TODO */ } BitArrayOption::Float { location: _ } => { /* TODO */ } BitArrayOption::Bits { location: _ } => { /* TODO */ } BitArrayOption::Utf8 { location: _ } => { /* TODO */ } BitArrayOption::Utf16 { location: _ } => { /* TODO */ } BitArrayOption::Utf32 { location: _ } => { /* TODO */ } BitArrayOption::Utf8Codepoint { location: _ } => { /* TODO */ } BitArrayOption::Utf16Codepoint { location: _ } => { /* TODO */ } BitArrayOption::Utf32Codepoint { location: _ } => { /* TODO */ } BitArrayOption::Signed { location: _ } => { /* TODO */ } BitArrayOption::Unsigned { location: _ } => { /* TODO */ } BitArrayOption::Big { location: _ } => { /* TODO */ } BitArrayOption::Little { location: _ } => { /* TODO */ } BitArrayOption::Native { location: _ } => { /* TODO */ } BitArrayOption::Size { location: _, value, short_form: _, } => { v.visit_typed_pattern(value); } BitArrayOption::Unit { location: _, value: _, } => { /* TODO */ } } } pub fn visit_typed_pattern_string_prefix<'a, V>( _v: &mut V, _location: &'a SrcSpan, _left_location: &'a SrcSpan, _left_side_assignment: &'a Option<(EcoString, SrcSpan)>, _right_location: &'a SrcSpan, _left_side_string: &'a EcoString, _right_side_assignment: &'a AssignName, ) where V: Visit<'a> + ?Sized, { } pub fn visit_typed_pattern_invalid<'a, V>(_v: &mut V, _location: &'a SrcSpan, _type_: &'a Arc) where V: Visit<'a> + ?Sized, { } pub fn visit_typed_expr_invalid<'a, V>( _v: &mut V, _location: &'a SrcSpan, _type_: &'a Arc, _extra_information: &'a Option, ) where V: Visit<'a> + ?Sized, { }