From ea3e6066137eea19845a7e423ca7da7be2e7765c Mon Sep 17 00:00:00 2001 From: Volkan Sagcan Date: Tue, 4 Jun 2024 13:33:26 +0200 Subject: [PATCH 01/13] init --- compiler/plc_diagnostics/src/diagnostics.rs | 16 +- .../src/diagnostics/diagnostics_registry.rs | 387 +++++------------- .../src/diagnostics/error_codes/E032.md | 14 +- src/builtins.rs | 16 +- src/index.rs | 4 + src/resolver/generics.rs | 2 +- src/validation/statement.rs | 65 ++- .../tests/assignment_validation_tests.rs | 112 +++++ ...ltins_called_with_invalid_param_count.snap | 18 +- ...ltins_called_with_invalid_param_count.snap | 14 +- ..._function_reports_invalid_param_count.snap | 10 +- ..._called_with_invalid_number_of_params.snap | 34 +- 12 files changed, 332 insertions(+), 360 deletions(-) diff --git a/compiler/plc_diagnostics/src/diagnostics.rs b/compiler/plc_diagnostics/src/diagnostics.rs index d45546a92d..55a52fff36 100644 --- a/compiler/plc_diagnostics/src/diagnostics.rs +++ b/compiler/plc_diagnostics/src/diagnostics.rs @@ -199,12 +199,16 @@ impl Diagnostic { .with_error_code("E006") } - pub fn invalid_parameter_count(expected: usize, received: usize, location: SourceLocation) -> Diagnostic { - Diagnostic::new( - format!( - "Invalid parameter count. Received {received} parameters while {expected} parameters were expected.", - )).with_error_code("E032") - .with_location(location) + pub fn invalid_argument_count( + expected: usize, + actual: usize, + location: impl Into, + ) -> Diagnostic { + Diagnostic::new(format!( + "this POU takes {expected} argument(s) but {actual} argument(s) were supplied", + )) + .with_error_code("E032") + .with_location(location.into()) } pub fn unknown_type(type_name: &str, location: SourceLocation) -> Diagnostic { diff --git a/compiler/plc_diagnostics/src/diagnostics/diagnostics_registry.rs b/compiler/plc_diagnostics/src/diagnostics/diagnostics_registry.rs index b9999558bc..a3bbbb7a3a 100644 --- a/compiler/plc_diagnostics/src/diagnostics/diagnostics_registry.rs +++ b/compiler/plc_diagnostics/src/diagnostics/diagnostics_registry.rs @@ -99,296 +99,107 @@ impl From<&DiagnosticsRegistry> for DiagnosticsConfiguration { } } +#[rustfmt::skip] lazy_static! { static ref DIAGNOSTICS: FxHashMap<&'static str, DiagnosticEntry> = add_diagnostic!( - E001, - Error, - include_str!("./error_codes/E001.md"), //General Error - E002, - Error, - include_str!("./error_codes/E002.md"), //General IO Error - E003, - Error, - include_str!("./error_codes/E003.md"), //Parameter Error - E004, - Error, - include_str!("./error_codes/E004.md"), //Duplicate Symbol - E005, - Error, - include_str!("./error_codes/E005.md"), //Generic LLVM Error - E006, - Error, - include_str!("./error_codes/E006.md"), //Missing Token - E007, - Error, - include_str!("./error_codes/E007.md"), //Unexpected Token - E008, - Error, - include_str!("./error_codes/E008.md"), //Invalid Range - E009, - Error, - include_str!("./error_codes/E009.md"), //Mismatched Parantheses - E010, - Error, - include_str!("./error_codes/E010.md"), //Invalid Time Literal - E011, - Error, - include_str!("./error_codes/E011.md"), //Invalid Number - E012, - Error, - include_str!("./error_codes/E012.md"), //Missing Case Condition - E013, - Warning, - include_str!("./error_codes/E013.md"), //Keywords shoud contain underscores - E014, - Warning, - include_str!("./error_codes/E014.md"), //Wrong parantheses type - E015, - Warning, - include_str!("./error_codes/E015.md"), //Pointer is not standard - E016, - Warning, - include_str!("./error_codes/E016.md"), //Return types cannot have a default value - E017, - Error, - include_str!("./error_codes/E017.md"), //Classes cannot contain implementations - E018, - Error, - include_str!("./error_codes/E018.md"), //Duplicate Label - E019, - Error, - include_str!("./error_codes/E019.md"), //Classes cannot contain IN_OUT variables - E020, - Error, - include_str!("./error_codes/E020.md"), //Classes cannot contain a return type - E021, - Error, - include_str!("./error_codes/E021.md"), //POUs cannot be extended - E022, - Warning, - include_str!("./error_codes/E022.md"), //Missing action container - E023, - Warning, - include_str!("./error_codes/E023.md"), //Statement with no effect - E024, - Warning, - include_str!("./error_codes/E024.md"), //Invalid pragma location - E025, - Error, - include_str!("./error_codes/E025.md"), // Missing return type - E026, - Error, - include_str!("./error_codes/E026.md"), - E027, - Error, - include_str!("./error_codes/E027.md"), - E028, - Error, - include_str!("./error_codes/E028.md"), - E029, - Error, - include_str!("./error_codes/E029.md"), - E030, - Error, - include_str!("./error_codes/E030.md"), - E031, - Error, - include_str!("./error_codes/E031.md"), - E032, - Error, - include_str!("./error_codes/E032.md"), - E033, - Error, - include_str!("./error_codes/E033.md"), - E034, - Error, - include_str!("./error_codes/E034.md"), - E035, - Error, - include_str!("./error_codes/E035.md"), - E036, - Error, - include_str!("./error_codes/E036.md"), - E037, - Error, - include_str!("./error_codes/E037.md"), - E038, - Error, - include_str!("./error_codes/E038.md"), //Missing type - E039, - Warning, - include_str!("./error_codes/E039.md"), - E040, - Error, - include_str!("./error_codes/E040.md"), - E041, - Error, - include_str!("./error_codes/E041.md"), - E042, - Warning, - include_str!("./error_codes/E042.md"), //Assignment to reference - E043, - Error, - include_str!("./error_codes/E043.md"), - E044, - Error, - include_str!("./error_codes/E044.md"), - E045, - Error, - include_str!("./error_codes/E045.md"), - E046, - Error, - include_str!("./error_codes/E046.md"), - E047, - Warning, - include_str!("./error_codes/E047.md"), //VLAs are always by reference - E048, - Error, - include_str!("./error_codes/E048.md"), - E049, - Error, - include_str!("./error_codes/E049.md"), - E050, - Error, - include_str!("./error_codes/E050.md"), - E051, - Error, - include_str!("./error_codes/E051.md"), - E052, - Error, - include_str!("./error_codes/E052.md"), - E053, - Error, - include_str!("./error_codes/E053.md"), - E054, - Error, - include_str!("./error_codes/E054.md"), - E055, - Error, - include_str!("./error_codes/E055.md"), - E056, - Error, - include_str!("./error_codes/E056.md"), - E057, - Error, - include_str!("./error_codes/E057.md"), - E058, - Error, - include_str!("./error_codes/E058.md"), - E059, - Error, - include_str!("./error_codes/E059.md"), - E060, - Info, - include_str!("./error_codes/E060.md"), //Variable direct access with % - E061, - Error, - include_str!("./error_codes/E061.md"), - E062, - Error, - include_str!("./error_codes/E062.md"), - E063, - Error, - include_str!("./error_codes/E063.md"), - E064, - Error, - include_str!("./error_codes/E064.md"), - E065, - Error, - include_str!("./error_codes/E065.md"), - E066, - Error, - include_str!("./error_codes/E066.md"), - E067, - Warning, - include_str!("./error_codes/E067.md"), //Implicit typecast - E068, - Error, - include_str!("./error_codes/E068.md"), - E069, - Error, - include_str!("./error_codes/E069.md"), - E070, - Error, - include_str!("./error_codes/E070.md"), - E071, - Error, - include_str!("./error_codes/E071.md"), - E072, - Error, - include_str!("./error_codes/E072.md"), - E073, - Error, - include_str!("./error_codes/E073.md"), - E074, - Error, - include_str!("./error_codes/E074.md"), - E075, - Error, - include_str!("./error_codes/E075.md"), - E076, - Error, - include_str!("./error_codes/E076.md"), - E077, - Error, - include_str!("./error_codes/E077.md"), - E078, - Error, - include_str!("./error_codes/E078.md"), - E079, - Error, - include_str!("./error_codes/E079.md"), - E080, - Error, - include_str!("./error_codes/E080.md"), - E081, - Error, - include_str!("./error_codes/E081.md"), - E082, - Error, - include_str!("./error_codes/E082.md"), - E083, - Error, - include_str!("./error_codes/E083.md"), - E084, - Error, - include_str!("./error_codes/E084.md"), - E085, - Error, - include_str!("./error_codes/E085.md"), - E086, - Error, - include_str!("./error_codes/E086.md"), - E087, - Error, - include_str!("./error_codes/E087.md"), - E088, - Error, - include_str!("./error_codes/E088.md"), - E089, - Error, - include_str!("./error_codes/E089.md"), - E090, - Warning, - include_str!("./error_codes/E090.md"), //Incompatible reference Assignment - E091, - Warning, - include_str!("./error_codes/E091.md"), - E092, - Info, - include_str!("./error_codes/E092.md"), - E093, - Warning, - include_str!("./error_codes/E093.md"), - E094, - Error, - include_str!("./error_codes/E094.md"), - E095, - Error, - include_str!("./error_codes/E095.md"), // Action call without `()` - E096, Warning, include_str!("./error_codes/E096.md"), // Integer Condition - E097, Error, include_str!("./error_codes/E097.md"), // Invalid Array Range -); + E001, Error, include_str!("./error_codes/E001.md"), //General Error + E002, Error, include_str!("./error_codes/E002.md"), //General IO Error + E003, Error, include_str!("./error_codes/E003.md"), //Parameter Error + E004, Error, include_str!("./error_codes/E004.md"), //Duplicate Symbol + E005, Error, include_str!("./error_codes/E005.md"), //Generic LLVM Error + E006, Error, include_str!("./error_codes/E006.md"), //Missing Token + E007, Error, include_str!("./error_codes/E007.md"), //Unexpected Token + E008, Error, include_str!("./error_codes/E008.md"), //Invalid Range + E009, Error, include_str!("./error_codes/E009.md"), //Mismatched Parantheses + E010, Error, include_str!("./error_codes/E010.md"), //Invalid Time Literal + E011, Error, include_str!("./error_codes/E011.md"), //Invalid Number + E012, Error, include_str!("./error_codes/E012.md"), //Missing Case Condition + E013, Warning, include_str!("./error_codes/E013.md"), //Keywords shoud contain underscores + E014, Warning, include_str!("./error_codes/E014.md"), //Wrong parantheses type + E015, Warning, include_str!("./error_codes/E015.md"), //Pointer is not standard + E016, Warning, include_str!("./error_codes/E016.md"), //Return types cannot have a default value + E017, Error, include_str!("./error_codes/E017.md"), //Classes cannot contain implementations + E018, Error, include_str!("./error_codes/E018.md"), //Duplicate Label + E019, Error, include_str!("./error_codes/E019.md"), //Classes cannot contain IN_OUT variables + E020, Error, include_str!("./error_codes/E020.md"), //Classes cannot contain a return type + E021, Error, include_str!("./error_codes/E021.md"), //POUs cannot be extended + E022, Warning, include_str!("./error_codes/E022.md"), //Missing action container + E023, Warning, include_str!("./error_codes/E023.md"), //Statement with no effect + E024, Warning, include_str!("./error_codes/E024.md"), //Invalid pragma location + E025, Error, include_str!("./error_codes/E025.md"), // Missing return type + E026, Error, include_str!("./error_codes/E026.md"), + E027, Error, include_str!("./error_codes/E027.md"), + E028, Error, include_str!("./error_codes/E028.md"), + E029, Error, include_str!("./error_codes/E029.md"), + E030, Error, include_str!("./error_codes/E030.md"), + E031, Error, include_str!("./error_codes/E031.md"), + E032, Error, include_str!("./error_codes/E032.md"), + E033, Error, include_str!("./error_codes/E033.md"), + E034, Error, include_str!("./error_codes/E034.md"), + E035, Error, include_str!("./error_codes/E035.md"), + E036, Error, include_str!("./error_codes/E036.md"), + E037, Error, include_str!("./error_codes/E037.md"), + E038, Error, include_str!("./error_codes/E038.md"), //Missing type + E039, Warning, include_str!("./error_codes/E039.md"), + E040, Error, include_str!("./error_codes/E040.md"), + E041, Error, include_str!("./error_codes/E041.md"), + E042, Warning, include_str!("./error_codes/E042.md"), //Assignment to reference + E043, Error, include_str!("./error_codes/E043.md"), + E044, Error, include_str!("./error_codes/E044.md"), + E045, Error, include_str!("./error_codes/E045.md"), + E046, Error, include_str!("./error_codes/E046.md"), + E047, Warning, include_str!("./error_codes/E047.md"), //VLAs are always by reference + E048, Error, include_str!("./error_codes/E048.md"), + E049, Error, include_str!("./error_codes/E049.md"), + E050, Error, include_str!("./error_codes/E050.md"), + E051, Error, include_str!("./error_codes/E051.md"), + E052, Error, include_str!("./error_codes/E052.md"), + E053, Error, include_str!("./error_codes/E053.md"), + E054, Error, include_str!("./error_codes/E054.md"), + E055, Error, include_str!("./error_codes/E055.md"), + E056, Error, include_str!("./error_codes/E056.md"), + E057, Error, include_str!("./error_codes/E057.md"), + E058, Error, include_str!("./error_codes/E058.md"), + E059, Error, include_str!("./error_codes/E059.md"), + E060, Info, include_str!("./error_codes/E060.md"), //Variable direct access with % + E061, Error, include_str!("./error_codes/E061.md"), + E062, Error, include_str!("./error_codes/E062.md"), + E063, Error, include_str!("./error_codes/E063.md"), + E064, Error, include_str!("./error_codes/E064.md"), + E065, Error, include_str!("./error_codes/E065.md"), + E066, Error, include_str!("./error_codes/E066.md"), + E067, Warning, include_str!("./error_codes/E067.md"), //Implicit typecast + E068, Error, include_str!("./error_codes/E068.md"), + E069, Error, include_str!("./error_codes/E069.md"), + E070, Error, include_str!("./error_codes/E070.md"), + E071, Error, include_str!("./error_codes/E071.md"), + E072, Error, include_str!("./error_codes/E072.md"), + E073, Error, include_str!("./error_codes/E073.md"), + E074, Error, include_str!("./error_codes/E074.md"), + E075, Error, include_str!("./error_codes/E075.md"), + E076, Error, include_str!("./error_codes/E076.md"), + E077, Error, include_str!("./error_codes/E077.md"), + E078, Error, include_str!("./error_codes/E078.md"), + E079, Error, include_str!("./error_codes/E079.md"), + E080, Error, include_str!("./error_codes/E080.md"), + E081, Error, include_str!("./error_codes/E081.md"), + E082, Error, include_str!("./error_codes/E082.md"), + E083, Error, include_str!("./error_codes/E083.md"), + E084, Error, include_str!("./error_codes/E084.md"), + E085, Error, include_str!("./error_codes/E085.md"), + E086, Error, include_str!("./error_codes/E086.md"), + E087, Error, include_str!("./error_codes/E087.md"), + E088, Error, include_str!("./error_codes/E088.md"), + E089, Error, include_str!("./error_codes/E089.md"), + E090, Warning, include_str!("./error_codes/E090.md"), //Incompatible reference Assignment + E091, Warning, include_str!("./error_codes/E091.md"), + E092, Info, include_str!("./error_codes/E092.md"), + E093, Warning, include_str!("./error_codes/E093.md"), + E094, Error, include_str!("./error_codes/E094.md"), + E095, Error, include_str!("./error_codes/E095.md"), // Action call without `()` + E096, Warning, include_str!("./error_codes/E096.md"), // Integer Condition + E097, Error, include_str!("./error_codes/E097.md"), // Invalid Array Range + ); } #[cfg(test)] diff --git a/compiler/plc_diagnostics/src/diagnostics/error_codes/E032.md b/compiler/plc_diagnostics/src/diagnostics/error_codes/E032.md index 53e170129c..018e82d940 100644 --- a/compiler/plc_diagnostics/src/diagnostics/error_codes/E032.md +++ b/compiler/plc_diagnostics/src/diagnostics/error_codes/E032.md @@ -1 +1,13 @@ -# Invalid number of parameters +# Invalid number of arguments + +An invalid number of arguments was passed to a POU. For example + +``` +FUNCTION foo + (* ... *) +END_FUNCTION + +FUNCTION main : DINT + foo('bar'); // Error, foo isn't expecting any arguments +END_FUNCTION +``` diff --git a/src/builtins.rs b/src/builtins.rs index 4deca18bb1..42e31392e9 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -92,14 +92,14 @@ lazy_static! { }), validation: Some(|validator, operator, parameters, _, _| { let Some(params) = parameters else { - validator.push_diagnostic(Diagnostic::invalid_parameter_count(1, 0, operator.get_location())); + validator.push_diagnostic(Diagnostic::invalid_argument_count(1, 0, operator.get_location())); return; }; let params = flatten_expression_list(params); if params.len() > 1 { - validator.push_diagnostic(Diagnostic::invalid_parameter_count(1, params.len(), operator.get_location())); + validator.push_diagnostic(Diagnostic::invalid_argument_count(1, params.len(), operator.get_location())); } }), generic_name_resolver: no_generic_name_resolver, @@ -579,7 +579,7 @@ fn validate_builtin_symbol_parameter_count( operation: Operator, ) { let Some(params) = parameters else { - validator.push_diagnostic(Diagnostic::invalid_parameter_count(2, 0, operator.get_location())); + validator.push_diagnostic(Diagnostic::invalid_argument_count(2, 0, operator.get_location())); return; }; @@ -588,7 +588,7 @@ fn validate_builtin_symbol_parameter_count( // non-extensible operators Operator::Minus | Operator::Division | Operator::NotEqual => { if count != 2 { - validator.push_diagnostic(Diagnostic::invalid_parameter_count( + validator.push_diagnostic(Diagnostic::invalid_argument_count( 2, count, operator.get_location(), @@ -597,7 +597,7 @@ fn validate_builtin_symbol_parameter_count( } _ => { if count < 2 { - validator.push_diagnostic(Diagnostic::invalid_parameter_count( + validator.push_diagnostic(Diagnostic::invalid_argument_count( 2, count, operator.get_location(), @@ -746,7 +746,7 @@ fn validate_variable_length_array_bound_function( index: &Index, ) { let Some(parameters) = parameters else { - validator.push_diagnostic(Diagnostic::invalid_parameter_count(2, 0, operator.get_location())); + validator.push_diagnostic(Diagnostic::invalid_argument_count(2, 0, operator.get_location())); // no params, nothing to validate return; }; @@ -754,7 +754,7 @@ fn validate_variable_length_array_bound_function( let params = ast::flatten_expression_list(parameters); if params.len() > 2 { - validator.push_diagnostic(Diagnostic::invalid_parameter_count( + validator.push_diagnostic(Diagnostic::invalid_argument_count( 2, params.len(), operator.get_location(), @@ -798,7 +798,7 @@ fn validate_variable_length_array_bound_function( }; } (Some(_), None) => { - validator.push_diagnostic(Diagnostic::invalid_parameter_count(2, 1, operator.get_location())) + validator.push_diagnostic(Diagnostic::invalid_argument_count(2, 1, operator.get_location())) } _ => unreachable!(), } diff --git a/src/index.rs b/src/index.rs index 0370ce073a..72fbd1a4c3 100644 --- a/src/index.rs +++ b/src/index.rs @@ -1199,6 +1199,10 @@ impl Index { .collect::>() } + pub fn has_variadic_parameter(&self, pout_name: &str) -> bool { + self.get_pou_members(pout_name).iter().any(|member| member.is_parameter() && member.is_variadic()) + } + /// returns some if the current index is a VAR_INPUT, VAR_IN_OUT or VAR_OUTPUT that is not a variadic argument /// In other words it returns some if the member variable at `index` of the given container is a possible parameter in /// the call to it diff --git a/src/resolver/generics.rs b/src/resolver/generics.rs index 7cea493142..379460b346 100644 --- a/src/resolver/generics.rs +++ b/src/resolver/generics.rs @@ -440,7 +440,7 @@ pub fn generic_name_resolver( .fold(qualified_name.to_string(), |accum, s| format!("{accum}__{s}")) // TODO: Naming convention (see plc_util/src/convention.rs) } -/// This method returns the qualified name, but has the same signature as the generic resover to be used in builtins +/// This method returns the qualified name, but has the same signature as the generic resolver to be used in builtins pub fn no_generic_name_resolver( qualified_name: &str, _: &[GenericBinding], diff --git a/src/validation/statement.rs b/src/validation/statement.rs index 4e6d8af18c..0b3bf40846 100644 --- a/src/validation/statement.rs +++ b/src/validation/statement.rs @@ -1131,7 +1131,7 @@ fn is_aggregate_type_missmatch(left_type: &DataType, right_type: &DataType, inde fn validate_call( validator: &mut Validator, operator: &AstNode, - parameters: Option<&AstNode>, + operator_arguments: Option<&AstNode>, context: &ValidationContext, ) { // visit called pou @@ -1140,20 +1140,24 @@ fn validate_call( if let Some(pou) = context.find_pou(operator) { // additional validation for builtin calls if necessary if let Some(validation) = builtins::get_builtin(pou.get_name()).and_then(BuiltIn::get_validation) { - validation(validator, operator, parameters, context.annotations, context.index) + validation(validator, operator, operator_arguments, context.annotations, context.index) } - let declared_parameters = context.index.get_declared_parameters(pou.get_name()); - let passed_parameters = parameters.map(flatten_expression_list).unwrap_or_default(); + let arguments = operator_arguments.map(flatten_expression_list).unwrap_or_default(); + let parameters = context.index.get_declared_parameters(pou.get_name()); - let mut are_implicit_parameters = true; + if builtins::get_builtin(pou.get_name()).is_none() { + validate_argument_count(context, validator, pou, &arguments, &operator.location); + } + + let mut argument_are_implicit = true; let mut variable_location_in_parent = vec![]; // validate parameters - for (i, param) in passed_parameters.iter().enumerate() { - match get_implicit_call_parameter(param, &declared_parameters, i) { + for (i, param) in arguments.iter().enumerate() { + match get_implicit_call_parameter(param, ¶meters, i) { Ok((parameter_location_in_parent, right, is_implicit)) => { - let left = declared_parameters.get(parameter_location_in_parent); + let left = parameters.get(parameter_location_in_parent); if let Some(left) = left { validate_call_by_ref(validator, left, param); // 'parameter location in parent' and 'variable location in parent' are not the same (e.g VAR blocks are not counted as param). @@ -1167,11 +1171,11 @@ fn validate_call( validate_assignment(validator, right, None, ¶m.get_location(), context); } - // mixing implicit and explicit parameters is not allowed - // allways compare to the first passed parameter + // mixing implicit and explicit arguments is not allowed + // allways compare to the first argument if i == 0 { - are_implicit_parameters = is_implicit; - } else if are_implicit_parameters != is_implicit { + argument_are_implicit = is_implicit; + } else if argument_are_implicit != is_implicit { validator.push_diagnostic( Diagnostic::new("Cannot mix implicit and explicit call parameters!") .with_error_code("E031") @@ -1202,7 +1206,7 @@ fn validate_call( return; } let declared_in_out_params: Vec<&&VariableIndexEntry> = - declared_parameters.iter().filter(|p| VariableType::InOut == p.get_variable_type()).collect(); + parameters.iter().filter(|p| VariableType::InOut == p.get_variable_type()).collect(); // if the called pou has declared inouts, we need to make sure that these were passed to the pou call if !declared_in_out_params.is_empty() { @@ -1220,7 +1224,7 @@ fn validate_call( } } else { // POU could not be found, we can still partially validate the passed parameters - if let Some(s) = parameters.as_ref() { + if let Some(s) = operator_arguments.as_ref() { visit_statement(validator, s, context); } } @@ -1484,6 +1488,39 @@ fn validate_assignment_type_sizes( }); } +fn validate_argument_count( + context: &ValidationContext, + validator: &mut Validator, + pou: &PouIndexEntry, + arguments: &[&AstNode], + operator_location: &SourceLocation, +) { + let parameters = context.index.get_declared_parameters(pou.get_name()); + let has_variadic_parameter = context.index.has_variadic_parameter(pou.get_name()); + + let argument_count_is_incorrect = match pou { + PouIndexEntry::Function { .. } => { + !((has_variadic_parameter && arguments.len() >= parameters.len()) + || (arguments.len() == parameters.len())) + } + + PouIndexEntry::Program { .. } | PouIndexEntry::FunctionBlock { .. } => { + arguments.len() > parameters.len() && !has_variadic_parameter + } + + // TODO: _ or match each variant? + _ => false, + }; + + if argument_count_is_incorrect { + validator.push_diagnostic(Diagnostic::invalid_argument_count( + parameters.len(), + arguments.len(), + operator_location, + )); + } +} + mod helper { use std::ops::Range; diff --git a/src/validation/tests/assignment_validation_tests.rs b/src/validation/tests/assignment_validation_tests.rs index 40da9e7fc4..b10718bc18 100644 --- a/src/validation/tests/assignment_validation_tests.rs +++ b/src/validation/tests/assignment_validation_tests.rs @@ -1217,3 +1217,115 @@ fn void_assignment_validation() { "###) } + +// TODO: Probably not the correct folder to place these tests in +#[test] +fn function_where_arguments_are_less_than_parameters() { + let diagnostics = parse_and_validate_buffered( + " + FUNCTION main : DINT + fn_with_one_parameter(); + fn_with_one_parameter(1, 2); + + fn_with_two_parameters(1); + fn_with_two_parameters(1, 2, 3); + + fn_with_three_parameters(1, 2); + fn_with_three_parameters(1, 2, 3, 4); + END_FUNCTION + + FUNCTION fn_with_one_parameter + VAR_INPUT + in_one : DINT; + END_VAR + END_FUNCTION + + FUNCTION fn_with_two_parameters + VAR_INPUT + in_one : DINT; + END_VAR + + VAR_OUTPUT + out_two : DINT; + END_VAR + END_FUNCTION + + FUNCTION fn_with_three_parameters + VAR_INPUT + in_one : DINT; + END_VAR + + VAR_OUTPUT + out_two : DINT; + END_VAR + + VAR_IN_OUT + inout_three : DINT; + END_VAR + END_FUNCTION + ", + ); + + assert_snapshot!(diagnostics, @r###" + error[E032]: this POU takes 1 argument(s) but 0 argument(s) were supplied + ┌─ :3:13 + │ + 3 │ fn_with_one_parameter(); + │ ^^^^^^^^^^^^^^^^^^^^^ this POU takes 1 argument(s) but 0 argument(s) were supplied + + error[E032]: this POU takes 1 argument(s) but 2 argument(s) were supplied + ┌─ :4:13 + │ + 4 │ fn_with_one_parameter(1, 2); + │ ^^^^^^^^^^^^^^^^^^^^^ this POU takes 1 argument(s) but 2 argument(s) were supplied + + error[E032]: this POU takes 2 argument(s) but 1 argument(s) were supplied + ┌─ :6:13 + │ + 6 │ fn_with_two_parameters(1); + │ ^^^^^^^^^^^^^^^^^^^^^^ this POU takes 2 argument(s) but 1 argument(s) were supplied + + error[E032]: this POU takes 2 argument(s) but 3 argument(s) were supplied + ┌─ :7:13 + │ + 7 │ fn_with_two_parameters(1, 2, 3); + │ ^^^^^^^^^^^^^^^^^^^^^^ this POU takes 2 argument(s) but 3 argument(s) were supplied + + error[E031]: Expected a reference for parameter out_two because their type is Output + ┌─ :7:39 + │ + 7 │ fn_with_two_parameters(1, 2, 3); + │ ^ Expected a reference for parameter out_two because their type is Output + + error[E032]: this POU takes 3 argument(s) but 2 argument(s) were supplied + ┌─ :9:13 + │ + 9 │ fn_with_three_parameters(1, 2); + │ ^^^^^^^^^^^^^^^^^^^^^^^^ this POU takes 3 argument(s) but 2 argument(s) were supplied + + error[E031]: Expected a reference for parameter out_two because their type is Output + ┌─ :9:41 + │ + 9 │ fn_with_three_parameters(1, 2); + │ ^ Expected a reference for parameter out_two because their type is Output + + error[E032]: this POU takes 3 argument(s) but 4 argument(s) were supplied + ┌─ :10:13 + │ + 10 │ fn_with_three_parameters(1, 2, 3, 4); + │ ^^^^^^^^^^^^^^^^^^^^^^^^ this POU takes 3 argument(s) but 4 argument(s) were supplied + + error[E031]: Expected a reference for parameter out_two because their type is Output + ┌─ :10:41 + │ + 10 │ fn_with_three_parameters(1, 2, 3, 4); + │ ^ Expected a reference for parameter out_two because their type is Output + + error[E031]: Expected a reference for parameter inout_three because their type is InOut + ┌─ :10:44 + │ + 10 │ fn_with_three_parameters(1, 2, 3, 4); + │ ^ Expected a reference for parameter inout_three because their type is InOut + + "###); +} diff --git a/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__arithmetic_builtins_called_with_invalid_param_count.snap b/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__arithmetic_builtins_called_with_invalid_param_count.snap index 118b727271..f0e7980f22 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__arithmetic_builtins_called_with_invalid_param_count.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__arithmetic_builtins_called_with_invalid_param_count.snap @@ -2,11 +2,11 @@ source: src/validation/tests/builtin_validation_tests.rs expression: "&diagnostics" --- -error[E032]: Invalid parameter count. Received 0 parameters while 2 parameters were expected. +error[E032]: this POU takes 2 argument(s) but 0 argument(s) were supplied ┌─ :7:13 │ 7 │ ADD(); - │ ^^^ Invalid parameter count. Received 0 parameters while 2 parameters were expected. + │ ^^^ this POU takes 2 argument(s) but 0 argument(s) were supplied error[E064]: Could not resolve generic type T with ANY_NUMBER ┌─ :7:13 @@ -14,22 +14,20 @@ error[E064]: Could not resolve generic type T with ANY_NUMBER 7 │ ADD(); │ ^^^^^^ Could not resolve generic type T with ANY_NUMBER -error[E032]: Invalid parameter count. Received 1 parameters while 2 parameters were expected. +error[E032]: this POU takes 2 argument(s) but 1 argument(s) were supplied ┌─ :8:13 │ 8 │ MUL(x1); - │ ^^^ Invalid parameter count. Received 1 parameters while 2 parameters were expected. + │ ^^^ this POU takes 2 argument(s) but 1 argument(s) were supplied -error[E032]: Invalid parameter count. Received 4 parameters while 2 parameters were expected. +error[E032]: this POU takes 2 argument(s) but 4 argument(s) were supplied ┌─ :9:13 │ 9 │ DIV(x2, x2, x1, x2); // DIV and SUB are not extensible - │ ^^^ Invalid parameter count. Received 4 parameters while 2 parameters were expected. + │ ^^^ this POU takes 2 argument(s) but 4 argument(s) were supplied -error[E032]: Invalid parameter count. Received 4 parameters while 2 parameters were expected. +error[E032]: this POU takes 2 argument(s) but 4 argument(s) were supplied ┌─ :10:13 │ 10 │ SUB(x2, x2, x1, x2); - │ ^^^ Invalid parameter count. Received 4 parameters while 2 parameters were expected. - - + │ ^^^ this POU takes 2 argument(s) but 4 argument(s) were supplied diff --git a/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__comparison_builtins_called_with_invalid_param_count.snap b/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__comparison_builtins_called_with_invalid_param_count.snap index cafd37f35c..bd32cc6bbb 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__comparison_builtins_called_with_invalid_param_count.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__comparison_builtins_called_with_invalid_param_count.snap @@ -2,22 +2,20 @@ source: src/validation/tests/builtin_validation_tests.rs expression: "&diagnostics" --- -error[E032]: Invalid parameter count. Received 0 parameters while 2 parameters were expected. +error[E032]: this POU takes 2 argument(s) but 0 argument(s) were supplied ┌─ :7:13 │ 7 │ EQ(); - │ ^^ Invalid parameter count. Received 0 parameters while 2 parameters were expected. + │ ^^ this POU takes 2 argument(s) but 0 argument(s) were supplied -error[E032]: Invalid parameter count. Received 1 parameters while 2 parameters were expected. +error[E032]: this POU takes 2 argument(s) but 1 argument(s) were supplied ┌─ :8:13 │ 8 │ GT(x1); - │ ^^ Invalid parameter count. Received 1 parameters while 2 parameters were expected. + │ ^^ this POU takes 2 argument(s) but 1 argument(s) were supplied -error[E032]: Invalid parameter count. Received 4 parameters while 2 parameters were expected. +error[E032]: this POU takes 2 argument(s) but 4 argument(s) were supplied ┌─ :10:13 │ 10 │ NE(x2, x2, x1, x2); // NE is not extensible - │ ^^ Invalid parameter count. Received 4 parameters while 2 parameters were expected. - - + │ ^^ this POU takes 2 argument(s) but 4 argument(s) were supplied diff --git a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__ref_builtin_function_reports_invalid_param_count.snap b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__ref_builtin_function_reports_invalid_param_count.snap index f30dceb1b4..3e1f65bfca 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__ref_builtin_function_reports_invalid_param_count.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__ref_builtin_function_reports_invalid_param_count.snap @@ -2,16 +2,14 @@ source: src/validation/tests/statement_validation_tests.rs expression: diagnostics --- -error[E032]: Invalid parameter count. Received 0 parameters while 1 parameters were expected. +error[E032]: this POU takes 1 argument(s) but 0 argument(s) were supplied ┌─ :7:13 │ 7 │ REF(); - │ ^^^ Invalid parameter count. Received 0 parameters while 1 parameters were expected. + │ ^^^ this POU takes 1 argument(s) but 0 argument(s) were supplied -error[E032]: Invalid parameter count. Received 4 parameters while 1 parameters were expected. +error[E032]: this POU takes 1 argument(s) but 4 argument(s) were supplied ┌─ :8:13 │ 8 │ REF(x, 1, 2, 'abc'); - │ ^^^ Invalid parameter count. Received 4 parameters while 1 parameters were expected. - - + │ ^^^ this POU takes 1 argument(s) but 4 argument(s) were supplied diff --git a/src/validation/tests/snapshots/rusty__validation__tests__variable_length_array_test__builtins__builtins_called_with_invalid_number_of_params.snap b/src/validation/tests/snapshots/rusty__validation__tests__variable_length_array_test__builtins__builtins_called_with_invalid_number_of_params.snap index 61e2cbe523..86fc486793 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__variable_length_array_test__builtins__builtins_called_with_invalid_number_of_params.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__variable_length_array_test__builtins__builtins_called_with_invalid_number_of_params.snap @@ -2,23 +2,23 @@ source: src/validation/tests/variable_length_array_test.rs expression: diagnostics --- -error[E032]: Invalid parameter count. Received 0 parameters while 2 parameters were expected. +error[E032]: this POU takes 2 argument(s) but 0 argument(s) were supplied ┌─ :13:13 │ 13 │ LOWER_BOUND(); - │ ^^^^^^^^^^^ Invalid parameter count. Received 0 parameters while 2 parameters were expected. + │ ^^^^^^^^^^^ this POU takes 2 argument(s) but 0 argument(s) were supplied -error[E032]: Invalid parameter count. Received 1 parameters while 2 parameters were expected. +error[E032]: this POU takes 2 argument(s) but 1 argument(s) were supplied ┌─ :14:13 │ 14 │ LOWER_BOUND(vla); - │ ^^^^^^^^^^^ Invalid parameter count. Received 1 parameters while 2 parameters were expected. + │ ^^^^^^^^^^^ this POU takes 2 argument(s) but 1 argument(s) were supplied -error[E032]: Invalid parameter count. Received 1 parameters while 2 parameters were expected. +error[E032]: this POU takes 2 argument(s) but 1 argument(s) were supplied ┌─ :15:13 │ 15 │ LOWER_BOUND(1); - │ ^^^^^^^^^^^ Invalid parameter count. Received 1 parameters while 2 parameters were expected. + │ ^^^^^^^^^^^ this POU takes 2 argument(s) but 1 argument(s) were supplied error[E031]: Expected a reference for parameter arr because their type is InOut ┌─ :15:25 @@ -32,29 +32,29 @@ error[E037]: Invalid assignment: cannot assign 'DINT' to 'VARIABLE LENGTH ARRAY' 15 │ LOWER_BOUND(1); │ ^ Invalid assignment: cannot assign 'DINT' to 'VARIABLE LENGTH ARRAY' -error[E032]: Invalid parameter count. Received 4 parameters while 2 parameters were expected. +error[E032]: this POU takes 2 argument(s) but 4 argument(s) were supplied ┌─ :16:13 │ 16 │ LOWER_BOUND(vla, 1, 2, 3); - │ ^^^^^^^^^^^ Invalid parameter count. Received 4 parameters while 2 parameters were expected. + │ ^^^^^^^^^^^ this POU takes 2 argument(s) but 4 argument(s) were supplied -error[E032]: Invalid parameter count. Received 0 parameters while 2 parameters were expected. +error[E032]: this POU takes 2 argument(s) but 0 argument(s) were supplied ┌─ :18:13 │ 18 │ UPPER_BOUND(); - │ ^^^^^^^^^^^ Invalid parameter count. Received 0 parameters while 2 parameters were expected. + │ ^^^^^^^^^^^ this POU takes 2 argument(s) but 0 argument(s) were supplied -error[E032]: Invalid parameter count. Received 1 parameters while 2 parameters were expected. +error[E032]: this POU takes 2 argument(s) but 1 argument(s) were supplied ┌─ :19:13 │ 19 │ UPPER_BOUND(vla); - │ ^^^^^^^^^^^ Invalid parameter count. Received 1 parameters while 2 parameters were expected. + │ ^^^^^^^^^^^ this POU takes 2 argument(s) but 1 argument(s) were supplied -error[E032]: Invalid parameter count. Received 1 parameters while 2 parameters were expected. +error[E032]: this POU takes 2 argument(s) but 1 argument(s) were supplied ┌─ :20:13 │ 20 │ UPPER_BOUND(1); - │ ^^^^^^^^^^^ Invalid parameter count. Received 1 parameters while 2 parameters were expected. + │ ^^^^^^^^^^^ this POU takes 2 argument(s) but 1 argument(s) were supplied error[E031]: Expected a reference for parameter arr because their type is InOut ┌─ :20:25 @@ -68,10 +68,8 @@ error[E037]: Invalid assignment: cannot assign 'DINT' to 'VARIABLE LENGTH ARRAY' 20 │ UPPER_BOUND(1); │ ^ Invalid assignment: cannot assign 'DINT' to 'VARIABLE LENGTH ARRAY' -error[E032]: Invalid parameter count. Received 4 parameters while 2 parameters were expected. +error[E032]: this POU takes 2 argument(s) but 4 argument(s) were supplied ┌─ :21:13 │ 21 │ UPPER_BOUND(vla, 1, 2, 3); - │ ^^^^^^^^^^^ Invalid parameter count. Received 4 parameters while 2 parameters were expected. - - + │ ^^^^^^^^^^^ this POU takes 2 argument(s) but 4 argument(s) were supplied From cd1040e1fc72e893cef3013d98779a5c3f159517 Mon Sep 17 00:00:00 2001 From: Volkan Sagcan Date: Tue, 4 Jun 2024 15:16:17 +0200 Subject: [PATCH 02/13] refactor: Add debug_assert and reformat registry --- compiler/plc_diagnostics/src/diagnostics.rs | 7 +++++-- .../src/diagnostics/diagnostics_registry.rs | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/plc_diagnostics/src/diagnostics.rs b/compiler/plc_diagnostics/src/diagnostics.rs index 55a52fff36..deb3f06712 100644 --- a/compiler/plc_diagnostics/src/diagnostics.rs +++ b/compiler/plc_diagnostics/src/diagnostics.rs @@ -2,6 +2,7 @@ use std::fmt::Display; use serde::{Deserialize, Serialize}; +use crate::diagnostics::diagnostics_registry::DIAGNOSTICS; use plc_ast::ast::AstNode; use plc_source::{ source_location::{SourceLocation, SourceLocationFactory}, @@ -88,8 +89,10 @@ impl Diagnostic { self } - pub fn with_error_code(mut self, error_code: &'static str) -> Self { - self.error_code = error_code; + pub fn with_error_code(mut self, code: &'static str) -> Self { + debug_assert!(DIAGNOSTICS.get(code).is_some(), "Error {code} does not exist"); + + self.error_code = code; self } diff --git a/compiler/plc_diagnostics/src/diagnostics/diagnostics_registry.rs b/compiler/plc_diagnostics/src/diagnostics/diagnostics_registry.rs index a3bbbb7a3a..f076bdf045 100644 --- a/compiler/plc_diagnostics/src/diagnostics/diagnostics_registry.rs +++ b/compiler/plc_diagnostics/src/diagnostics/diagnostics_registry.rs @@ -101,7 +101,7 @@ impl From<&DiagnosticsRegistry> for DiagnosticsConfiguration { #[rustfmt::skip] lazy_static! { - static ref DIAGNOSTICS: FxHashMap<&'static str, DiagnosticEntry> = add_diagnostic!( + pub static ref DIAGNOSTICS: FxHashMap<&'static str, DiagnosticEntry> = add_diagnostic!( E001, Error, include_str!("./error_codes/E001.md"), //General Error E002, Error, include_str!("./error_codes/E002.md"), //General IO Error E003, Error, include_str!("./error_codes/E003.md"), //Parameter Error From 2bd0bd532217308162ddce222658fb74c01e64bb Mon Sep 17 00:00:00 2001 From: Volkan Sagcan Date: Tue, 4 Jun 2024 15:35:01 +0200 Subject: [PATCH 03/13] chore: Improve error description --- compiler/plc_diagnostics/src/diagnostics/error_codes/E032.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/plc_diagnostics/src/diagnostics/error_codes/E032.md b/compiler/plc_diagnostics/src/diagnostics/error_codes/E032.md index 018e82d940..6a8380ce63 100644 --- a/compiler/plc_diagnostics/src/diagnostics/error_codes/E032.md +++ b/compiler/plc_diagnostics/src/diagnostics/error_codes/E032.md @@ -11,3 +11,7 @@ FUNCTION main : DINT foo('bar'); // Error, foo isn't expecting any arguments END_FUNCTION ``` + +Note that for `FUNCTION`s the argument count must match with the declared parameters and can be bigger if a variadic +parameter is present. For stateful POUs the argument count can be shorter than the declared parameters or be bigger +**if** variadic parameters are declared. This is because `VAR_INPUT`, `VAR_OUTPUT` arguments are optional. \ No newline at end of file From 49a7deb607a094e019dafbdb2dd832987e3fee49 Mon Sep 17 00:00:00 2001 From: Volkan Sagcan Date: Tue, 4 Jun 2024 15:35:38 +0200 Subject: [PATCH 04/13] Cleanup --- compiler/plc_diagnostics/src/diagnostics.rs | 9 ++++----- .../plc_diagnostics/src/diagnostics/error_codes/E032.md | 7 ++++--- src/validation/statement.rs | 1 - 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/plc_diagnostics/src/diagnostics.rs b/compiler/plc_diagnostics/src/diagnostics.rs index deb3f06712..785240d250 100644 --- a/compiler/plc_diagnostics/src/diagnostics.rs +++ b/compiler/plc_diagnostics/src/diagnostics.rs @@ -202,11 +202,10 @@ impl Diagnostic { .with_error_code("E006") } - pub fn invalid_argument_count( - expected: usize, - actual: usize, - location: impl Into, - ) -> Diagnostic { + pub fn invalid_argument_count(expected: usize, actual: usize, location: T) -> Diagnostic + where + T: Into, + { Diagnostic::new(format!( "this POU takes {expected} argument(s) but {actual} argument(s) were supplied", )) diff --git a/compiler/plc_diagnostics/src/diagnostics/error_codes/E032.md b/compiler/plc_diagnostics/src/diagnostics/error_codes/E032.md index 6a8380ce63..2762d3526d 100644 --- a/compiler/plc_diagnostics/src/diagnostics/error_codes/E032.md +++ b/compiler/plc_diagnostics/src/diagnostics/error_codes/E032.md @@ -12,6 +12,7 @@ FUNCTION main : DINT END_FUNCTION ``` -Note that for `FUNCTION`s the argument count must match with the declared parameters and can be bigger if a variadic -parameter is present. For stateful POUs the argument count can be shorter than the declared parameters or be bigger -**if** variadic parameters are declared. This is because `VAR_INPUT`, `VAR_OUTPUT` arguments are optional. \ No newline at end of file +Note that for `FUNCTION`s the argument count must match with the parameter list and can be bigger if a variadic +parameter is present. For stateful POUs variadic parameters are not supported, thus the argument count must be equal or +less than the parameter list depending on whether optional arguments such as `VAR_INPUT` or `VAR_OUTPUT` were not +passed. \ No newline at end of file diff --git a/src/validation/statement.rs b/src/validation/statement.rs index 0b3bf40846..f017abddea 100644 --- a/src/validation/statement.rs +++ b/src/validation/statement.rs @@ -1508,7 +1508,6 @@ fn validate_argument_count( arguments.len() > parameters.len() && !has_variadic_parameter } - // TODO: _ or match each variant? _ => false, }; From 8dff5e9b04a7d91e433be6a4b737a5788f86a224 Mon Sep 17 00:00:00 2001 From: Volkan Sagcan Date: Wed, 5 Jun 2024 10:02:43 +0200 Subject: [PATCH 05/13] =?UTF-8?q?=F0=9F=95=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler/plc_diagnostics/src/diagnostics.rs | 12 ++++++- .../tests/assignment_validation_tests.rs | 24 +++++++------- ...ltins_called_with_invalid_param_count.snap | 16 +++++----- ...ltins_called_with_invalid_param_count.snap | 12 +++---- ..._function_reports_invalid_param_count.snap | 8 ++--- ..._called_with_invalid_number_of_params.snap | 32 +++++++++---------- 6 files changed, 57 insertions(+), 47 deletions(-) diff --git a/compiler/plc_diagnostics/src/diagnostics.rs b/compiler/plc_diagnostics/src/diagnostics.rs index 785240d250..c6fc5470a2 100644 --- a/compiler/plc_diagnostics/src/diagnostics.rs +++ b/compiler/plc_diagnostics/src/diagnostics.rs @@ -206,8 +206,18 @@ impl Diagnostic { where T: Into, { + // Let's be extra fancy here 🕺 + fn message(value: usize) -> String { + match value { + 1 => format!("{value} argument"), + _ => format!("{value} arguments"), + } + } + Diagnostic::new(format!( - "this POU takes {expected} argument(s) but {actual} argument(s) were supplied", + "this POU takes {expected} but {actual} were supplied", + expected = message(expected), + actual = message(actual) )) .with_error_code("E032") .with_location(location.into()) diff --git a/src/validation/tests/assignment_validation_tests.rs b/src/validation/tests/assignment_validation_tests.rs index b10718bc18..854fb25e66 100644 --- a/src/validation/tests/assignment_validation_tests.rs +++ b/src/validation/tests/assignment_validation_tests.rs @@ -1267,29 +1267,29 @@ fn function_where_arguments_are_less_than_parameters() { ); assert_snapshot!(diagnostics, @r###" - error[E032]: this POU takes 1 argument(s) but 0 argument(s) were supplied + error[E032]: this POU takes 1 argument but 0 arguments were supplied ┌─ :3:13 │ 3 │ fn_with_one_parameter(); - │ ^^^^^^^^^^^^^^^^^^^^^ this POU takes 1 argument(s) but 0 argument(s) were supplied + │ ^^^^^^^^^^^^^^^^^^^^^ this POU takes 1 argument but 0 arguments were supplied - error[E032]: this POU takes 1 argument(s) but 2 argument(s) were supplied + error[E032]: this POU takes 1 argument but 2 arguments were supplied ┌─ :4:13 │ 4 │ fn_with_one_parameter(1, 2); - │ ^^^^^^^^^^^^^^^^^^^^^ this POU takes 1 argument(s) but 2 argument(s) were supplied + │ ^^^^^^^^^^^^^^^^^^^^^ this POU takes 1 argument but 2 arguments were supplied - error[E032]: this POU takes 2 argument(s) but 1 argument(s) were supplied + error[E032]: this POU takes 2 arguments but 1 argument were supplied ┌─ :6:13 │ 6 │ fn_with_two_parameters(1); - │ ^^^^^^^^^^^^^^^^^^^^^^ this POU takes 2 argument(s) but 1 argument(s) were supplied + │ ^^^^^^^^^^^^^^^^^^^^^^ this POU takes 2 arguments but 1 argument were supplied - error[E032]: this POU takes 2 argument(s) but 3 argument(s) were supplied + error[E032]: this POU takes 2 arguments but 3 arguments were supplied ┌─ :7:13 │ 7 │ fn_with_two_parameters(1, 2, 3); - │ ^^^^^^^^^^^^^^^^^^^^^^ this POU takes 2 argument(s) but 3 argument(s) were supplied + │ ^^^^^^^^^^^^^^^^^^^^^^ this POU takes 2 arguments but 3 arguments were supplied error[E031]: Expected a reference for parameter out_two because their type is Output ┌─ :7:39 @@ -1297,11 +1297,11 @@ fn function_where_arguments_are_less_than_parameters() { 7 │ fn_with_two_parameters(1, 2, 3); │ ^ Expected a reference for parameter out_two because their type is Output - error[E032]: this POU takes 3 argument(s) but 2 argument(s) were supplied + error[E032]: this POU takes 3 arguments but 2 arguments were supplied ┌─ :9:13 │ 9 │ fn_with_three_parameters(1, 2); - │ ^^^^^^^^^^^^^^^^^^^^^^^^ this POU takes 3 argument(s) but 2 argument(s) were supplied + │ ^^^^^^^^^^^^^^^^^^^^^^^^ this POU takes 3 arguments but 2 arguments were supplied error[E031]: Expected a reference for parameter out_two because their type is Output ┌─ :9:41 @@ -1309,11 +1309,11 @@ fn function_where_arguments_are_less_than_parameters() { 9 │ fn_with_three_parameters(1, 2); │ ^ Expected a reference for parameter out_two because their type is Output - error[E032]: this POU takes 3 argument(s) but 4 argument(s) were supplied + error[E032]: this POU takes 3 arguments but 4 arguments were supplied ┌─ :10:13 │ 10 │ fn_with_three_parameters(1, 2, 3, 4); - │ ^^^^^^^^^^^^^^^^^^^^^^^^ this POU takes 3 argument(s) but 4 argument(s) were supplied + │ ^^^^^^^^^^^^^^^^^^^^^^^^ this POU takes 3 arguments but 4 arguments were supplied error[E031]: Expected a reference for parameter out_two because their type is Output ┌─ :10:41 diff --git a/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__arithmetic_builtins_called_with_invalid_param_count.snap b/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__arithmetic_builtins_called_with_invalid_param_count.snap index f0e7980f22..505f01eddb 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__arithmetic_builtins_called_with_invalid_param_count.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__arithmetic_builtins_called_with_invalid_param_count.snap @@ -2,11 +2,11 @@ source: src/validation/tests/builtin_validation_tests.rs expression: "&diagnostics" --- -error[E032]: this POU takes 2 argument(s) but 0 argument(s) were supplied +error[E032]: this POU takes 2 arguments but 0 arguments were supplied ┌─ :7:13 │ 7 │ ADD(); - │ ^^^ this POU takes 2 argument(s) but 0 argument(s) were supplied + │ ^^^ this POU takes 2 arguments but 0 arguments were supplied error[E064]: Could not resolve generic type T with ANY_NUMBER ┌─ :7:13 @@ -14,20 +14,20 @@ error[E064]: Could not resolve generic type T with ANY_NUMBER 7 │ ADD(); │ ^^^^^^ Could not resolve generic type T with ANY_NUMBER -error[E032]: this POU takes 2 argument(s) but 1 argument(s) were supplied +error[E032]: this POU takes 2 arguments but 1 argument were supplied ┌─ :8:13 │ 8 │ MUL(x1); - │ ^^^ this POU takes 2 argument(s) but 1 argument(s) were supplied + │ ^^^ this POU takes 2 arguments but 1 argument were supplied -error[E032]: this POU takes 2 argument(s) but 4 argument(s) were supplied +error[E032]: this POU takes 2 arguments but 4 arguments were supplied ┌─ :9:13 │ 9 │ DIV(x2, x2, x1, x2); // DIV and SUB are not extensible - │ ^^^ this POU takes 2 argument(s) but 4 argument(s) were supplied + │ ^^^ this POU takes 2 arguments but 4 arguments were supplied -error[E032]: this POU takes 2 argument(s) but 4 argument(s) were supplied +error[E032]: this POU takes 2 arguments but 4 arguments were supplied ┌─ :10:13 │ 10 │ SUB(x2, x2, x1, x2); - │ ^^^ this POU takes 2 argument(s) but 4 argument(s) were supplied + │ ^^^ this POU takes 2 arguments but 4 arguments were supplied diff --git a/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__comparison_builtins_called_with_invalid_param_count.snap b/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__comparison_builtins_called_with_invalid_param_count.snap index bd32cc6bbb..492bcc0fd5 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__comparison_builtins_called_with_invalid_param_count.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__comparison_builtins_called_with_invalid_param_count.snap @@ -2,20 +2,20 @@ source: src/validation/tests/builtin_validation_tests.rs expression: "&diagnostics" --- -error[E032]: this POU takes 2 argument(s) but 0 argument(s) were supplied +error[E032]: this POU takes 2 arguments but 0 arguments were supplied ┌─ :7:13 │ 7 │ EQ(); - │ ^^ this POU takes 2 argument(s) but 0 argument(s) were supplied + │ ^^ this POU takes 2 arguments but 0 arguments were supplied -error[E032]: this POU takes 2 argument(s) but 1 argument(s) were supplied +error[E032]: this POU takes 2 arguments but 1 argument were supplied ┌─ :8:13 │ 8 │ GT(x1); - │ ^^ this POU takes 2 argument(s) but 1 argument(s) were supplied + │ ^^ this POU takes 2 arguments but 1 argument were supplied -error[E032]: this POU takes 2 argument(s) but 4 argument(s) were supplied +error[E032]: this POU takes 2 arguments but 4 arguments were supplied ┌─ :10:13 │ 10 │ NE(x2, x2, x1, x2); // NE is not extensible - │ ^^ this POU takes 2 argument(s) but 4 argument(s) were supplied + │ ^^ this POU takes 2 arguments but 4 arguments were supplied diff --git a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__ref_builtin_function_reports_invalid_param_count.snap b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__ref_builtin_function_reports_invalid_param_count.snap index 3e1f65bfca..02950337cb 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__ref_builtin_function_reports_invalid_param_count.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__statement_validation_tests__ref_builtin_function_reports_invalid_param_count.snap @@ -2,14 +2,14 @@ source: src/validation/tests/statement_validation_tests.rs expression: diagnostics --- -error[E032]: this POU takes 1 argument(s) but 0 argument(s) were supplied +error[E032]: this POU takes 1 argument but 0 arguments were supplied ┌─ :7:13 │ 7 │ REF(); - │ ^^^ this POU takes 1 argument(s) but 0 argument(s) were supplied + │ ^^^ this POU takes 1 argument but 0 arguments were supplied -error[E032]: this POU takes 1 argument(s) but 4 argument(s) were supplied +error[E032]: this POU takes 1 argument but 4 arguments were supplied ┌─ :8:13 │ 8 │ REF(x, 1, 2, 'abc'); - │ ^^^ this POU takes 1 argument(s) but 4 argument(s) were supplied + │ ^^^ this POU takes 1 argument but 4 arguments were supplied diff --git a/src/validation/tests/snapshots/rusty__validation__tests__variable_length_array_test__builtins__builtins_called_with_invalid_number_of_params.snap b/src/validation/tests/snapshots/rusty__validation__tests__variable_length_array_test__builtins__builtins_called_with_invalid_number_of_params.snap index 86fc486793..b249f97e45 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__variable_length_array_test__builtins__builtins_called_with_invalid_number_of_params.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__variable_length_array_test__builtins__builtins_called_with_invalid_number_of_params.snap @@ -2,23 +2,23 @@ source: src/validation/tests/variable_length_array_test.rs expression: diagnostics --- -error[E032]: this POU takes 2 argument(s) but 0 argument(s) were supplied +error[E032]: this POU takes 2 arguments but 0 arguments were supplied ┌─ :13:13 │ 13 │ LOWER_BOUND(); - │ ^^^^^^^^^^^ this POU takes 2 argument(s) but 0 argument(s) were supplied + │ ^^^^^^^^^^^ this POU takes 2 arguments but 0 arguments were supplied -error[E032]: this POU takes 2 argument(s) but 1 argument(s) were supplied +error[E032]: this POU takes 2 arguments but 1 argument were supplied ┌─ :14:13 │ 14 │ LOWER_BOUND(vla); - │ ^^^^^^^^^^^ this POU takes 2 argument(s) but 1 argument(s) were supplied + │ ^^^^^^^^^^^ this POU takes 2 arguments but 1 argument were supplied -error[E032]: this POU takes 2 argument(s) but 1 argument(s) were supplied +error[E032]: this POU takes 2 arguments but 1 argument were supplied ┌─ :15:13 │ 15 │ LOWER_BOUND(1); - │ ^^^^^^^^^^^ this POU takes 2 argument(s) but 1 argument(s) were supplied + │ ^^^^^^^^^^^ this POU takes 2 arguments but 1 argument were supplied error[E031]: Expected a reference for parameter arr because their type is InOut ┌─ :15:25 @@ -32,29 +32,29 @@ error[E037]: Invalid assignment: cannot assign 'DINT' to 'VARIABLE LENGTH ARRAY' 15 │ LOWER_BOUND(1); │ ^ Invalid assignment: cannot assign 'DINT' to 'VARIABLE LENGTH ARRAY' -error[E032]: this POU takes 2 argument(s) but 4 argument(s) were supplied +error[E032]: this POU takes 2 arguments but 4 arguments were supplied ┌─ :16:13 │ 16 │ LOWER_BOUND(vla, 1, 2, 3); - │ ^^^^^^^^^^^ this POU takes 2 argument(s) but 4 argument(s) were supplied + │ ^^^^^^^^^^^ this POU takes 2 arguments but 4 arguments were supplied -error[E032]: this POU takes 2 argument(s) but 0 argument(s) were supplied +error[E032]: this POU takes 2 arguments but 0 arguments were supplied ┌─ :18:13 │ 18 │ UPPER_BOUND(); - │ ^^^^^^^^^^^ this POU takes 2 argument(s) but 0 argument(s) were supplied + │ ^^^^^^^^^^^ this POU takes 2 arguments but 0 arguments were supplied -error[E032]: this POU takes 2 argument(s) but 1 argument(s) were supplied +error[E032]: this POU takes 2 arguments but 1 argument were supplied ┌─ :19:13 │ 19 │ UPPER_BOUND(vla); - │ ^^^^^^^^^^^ this POU takes 2 argument(s) but 1 argument(s) were supplied + │ ^^^^^^^^^^^ this POU takes 2 arguments but 1 argument were supplied -error[E032]: this POU takes 2 argument(s) but 1 argument(s) were supplied +error[E032]: this POU takes 2 arguments but 1 argument were supplied ┌─ :20:13 │ 20 │ UPPER_BOUND(1); - │ ^^^^^^^^^^^ this POU takes 2 argument(s) but 1 argument(s) were supplied + │ ^^^^^^^^^^^ this POU takes 2 arguments but 1 argument were supplied error[E031]: Expected a reference for parameter arr because their type is InOut ┌─ :20:25 @@ -68,8 +68,8 @@ error[E037]: Invalid assignment: cannot assign 'DINT' to 'VARIABLE LENGTH ARRAY' 20 │ UPPER_BOUND(1); │ ^ Invalid assignment: cannot assign 'DINT' to 'VARIABLE LENGTH ARRAY' -error[E032]: this POU takes 2 argument(s) but 4 argument(s) were supplied +error[E032]: this POU takes 2 arguments but 4 arguments were supplied ┌─ :21:13 │ 21 │ UPPER_BOUND(vla, 1, 2, 3); - │ ^^^^^^^^^^^ this POU takes 2 argument(s) but 4 argument(s) were supplied + │ ^^^^^^^^^^^ this POU takes 2 arguments but 4 arguments were supplied From 29e96f486fc3263ba74a8caaa955c32e55adc215 Mon Sep 17 00:00:00 2001 From: Volkan Sagcan Date: Wed, 5 Jun 2024 10:31:14 +0200 Subject: [PATCH 06/13] finalize --- src/validation/statement.rs | 3 + .../tests/assignment_validation_tests.rs | 112 ------------- .../tests/statement_validation_tests.rs | 154 ++++++++++++++++++ 3 files changed, 157 insertions(+), 112 deletions(-) diff --git a/src/validation/statement.rs b/src/validation/statement.rs index f017abddea..8c65b3fb17 100644 --- a/src/validation/statement.rs +++ b/src/validation/statement.rs @@ -1488,6 +1488,9 @@ fn validate_assignment_type_sizes( }); } +/// Validates if a POU call has the correct amount of arguments. Specifically for functions the +/// argument count must be greater or equal depending on if a variadic parameter is present whereas for +/// stateful POUs the argument count can be less since VAR_INPUT and VAR_OUTPUT arguments are optional fn validate_argument_count( context: &ValidationContext, validator: &mut Validator, diff --git a/src/validation/tests/assignment_validation_tests.rs b/src/validation/tests/assignment_validation_tests.rs index 854fb25e66..40da9e7fc4 100644 --- a/src/validation/tests/assignment_validation_tests.rs +++ b/src/validation/tests/assignment_validation_tests.rs @@ -1217,115 +1217,3 @@ fn void_assignment_validation() { "###) } - -// TODO: Probably not the correct folder to place these tests in -#[test] -fn function_where_arguments_are_less_than_parameters() { - let diagnostics = parse_and_validate_buffered( - " - FUNCTION main : DINT - fn_with_one_parameter(); - fn_with_one_parameter(1, 2); - - fn_with_two_parameters(1); - fn_with_two_parameters(1, 2, 3); - - fn_with_three_parameters(1, 2); - fn_with_three_parameters(1, 2, 3, 4); - END_FUNCTION - - FUNCTION fn_with_one_parameter - VAR_INPUT - in_one : DINT; - END_VAR - END_FUNCTION - - FUNCTION fn_with_two_parameters - VAR_INPUT - in_one : DINT; - END_VAR - - VAR_OUTPUT - out_two : DINT; - END_VAR - END_FUNCTION - - FUNCTION fn_with_three_parameters - VAR_INPUT - in_one : DINT; - END_VAR - - VAR_OUTPUT - out_two : DINT; - END_VAR - - VAR_IN_OUT - inout_three : DINT; - END_VAR - END_FUNCTION - ", - ); - - assert_snapshot!(diagnostics, @r###" - error[E032]: this POU takes 1 argument but 0 arguments were supplied - ┌─ :3:13 - │ - 3 │ fn_with_one_parameter(); - │ ^^^^^^^^^^^^^^^^^^^^^ this POU takes 1 argument but 0 arguments were supplied - - error[E032]: this POU takes 1 argument but 2 arguments were supplied - ┌─ :4:13 - │ - 4 │ fn_with_one_parameter(1, 2); - │ ^^^^^^^^^^^^^^^^^^^^^ this POU takes 1 argument but 2 arguments were supplied - - error[E032]: this POU takes 2 arguments but 1 argument were supplied - ┌─ :6:13 - │ - 6 │ fn_with_two_parameters(1); - │ ^^^^^^^^^^^^^^^^^^^^^^ this POU takes 2 arguments but 1 argument were supplied - - error[E032]: this POU takes 2 arguments but 3 arguments were supplied - ┌─ :7:13 - │ - 7 │ fn_with_two_parameters(1, 2, 3); - │ ^^^^^^^^^^^^^^^^^^^^^^ this POU takes 2 arguments but 3 arguments were supplied - - error[E031]: Expected a reference for parameter out_two because their type is Output - ┌─ :7:39 - │ - 7 │ fn_with_two_parameters(1, 2, 3); - │ ^ Expected a reference for parameter out_two because their type is Output - - error[E032]: this POU takes 3 arguments but 2 arguments were supplied - ┌─ :9:13 - │ - 9 │ fn_with_three_parameters(1, 2); - │ ^^^^^^^^^^^^^^^^^^^^^^^^ this POU takes 3 arguments but 2 arguments were supplied - - error[E031]: Expected a reference for parameter out_two because their type is Output - ┌─ :9:41 - │ - 9 │ fn_with_three_parameters(1, 2); - │ ^ Expected a reference for parameter out_two because their type is Output - - error[E032]: this POU takes 3 arguments but 4 arguments were supplied - ┌─ :10:13 - │ - 10 │ fn_with_three_parameters(1, 2, 3, 4); - │ ^^^^^^^^^^^^^^^^^^^^^^^^ this POU takes 3 arguments but 4 arguments were supplied - - error[E031]: Expected a reference for parameter out_two because their type is Output - ┌─ :10:41 - │ - 10 │ fn_with_three_parameters(1, 2, 3, 4); - │ ^ Expected a reference for parameter out_two because their type is Output - - error[E031]: Expected a reference for parameter inout_three because their type is InOut - ┌─ :10:44 - │ - 10 │ fn_with_three_parameters(1, 2, 3, 4); - │ ^ Expected a reference for parameter inout_three because their type is InOut - - "###); -} diff --git a/src/validation/tests/statement_validation_tests.rs b/src/validation/tests/statement_validation_tests.rs index fe186996be..1a873b3407 100644 --- a/src/validation/tests/statement_validation_tests.rs +++ b/src/validation/tests/statement_validation_tests.rs @@ -1667,3 +1667,157 @@ fn action_assignment_attempt_does_not_report_missing_parentheses() { "###); } + +#[test] +fn incorrect_argument_count_stateless_pous() { + let diagnostics = parse_and_validate_buffered( + " + FUNCTION main : DINT + fn_with_one_parameter(); + fn_with_one_parameter(1, 2); + + fn_with_two_parameters(1); + fn_with_two_parameters(1, 2, 3); + + fn_with_one_variadic_parameter(); + fn_with_one_variadic_parameter(1); + fn_with_one_variadic_parameter(1, 2); + fn_with_one_variadic_parameter(1, 2, 3); + END_FUNCTION + + FUNCTION fn_with_one_parameter + VAR_INPUT + in_one : DINT; + END_VAR + END_FUNCTION + + FUNCTION fn_with_two_parameters + VAR_INPUT + in_one : DINT; + END_VAR + + VAR_OUTPUT + out_two : DINT; + END_VAR + END_FUNCTION + + FUNCTION fn_with_one_variadic_parameter + VAR_INPUT + vararg: DINT...; + END_VAR + END_FUNCTION + ", + ); + + assert_snapshot!(diagnostics, @r###" + error[E032]: this POU takes 1 argument but 0 arguments were supplied + ┌─ :3:13 + │ + 3 │ fn_with_one_parameter(); + │ ^^^^^^^^^^^^^^^^^^^^^ this POU takes 1 argument but 0 arguments were supplied + + error[E032]: this POU takes 1 argument but 2 arguments were supplied + ┌─ :4:13 + │ + 4 │ fn_with_one_parameter(1, 2); + │ ^^^^^^^^^^^^^^^^^^^^^ this POU takes 1 argument but 2 arguments were supplied + + error[E032]: this POU takes 2 arguments but 1 argument were supplied + ┌─ :6:13 + │ + 6 │ fn_with_two_parameters(1); + │ ^^^^^^^^^^^^^^^^^^^^^^ this POU takes 2 arguments but 1 argument were supplied + + error[E032]: this POU takes 2 arguments but 3 arguments were supplied + ┌─ :7:13 + │ + 7 │ fn_with_two_parameters(1, 2, 3); + │ ^^^^^^^^^^^^^^^^^^^^^^ this POU takes 2 arguments but 3 arguments were supplied + + error[E031]: Expected a reference for parameter out_two because their type is Output + ┌─ :7:39 + │ + 7 │ fn_with_two_parameters(1, 2, 3); + │ ^ Expected a reference for parameter out_two because their type is Output + + "###); +} + +#[test] +fn incorrect_argument_count_stateful_pous() { + let source = r" + FUNCTION main : DINT + VAR + one_instance : fn_with_one_parameter; + two_instance : fn_with_two_parameters; + END_VAR + + one_instance(); + one_instance(1, 2); + + two_instance(1); + two_instance(1, 2, 3); + END_FUNCTION + + fn_with_one_parameter + VAR_INPUT + in_one : DINT; + END_VAR + END_ + + fn_with_two_parameters + VAR_INPUT + in_one : DINT; + END_VAR + + VAR_OUTPUT + out_two : DINT; + END_VAR + END_ + + "; + + let diagnostics = parse_and_validate_buffered(&source.replace("", "FUNCTION_BLOCK")); + assert_snapshot!(diagnostics, @r###" + error[E032]: this POU takes 1 argument but 2 arguments were supplied + ┌─ :9:13 + │ + 9 │ one_instance(1, 2); + │ ^^^^^^^^^^^^ this POU takes 1 argument but 2 arguments were supplied + + error[E032]: this POU takes 2 arguments but 3 arguments were supplied + ┌─ :12:13 + │ + 12 │ two_instance(1, 2, 3); + │ ^^^^^^^^^^^^ this POU takes 2 arguments but 3 arguments were supplied + + error[E031]: Expected a reference for parameter out_two because their type is Output + ┌─ :12:29 + │ + 12 │ two_instance(1, 2, 3); + │ ^ Expected a reference for parameter out_two because their type is Output + + "###); + + let diagnostics = parse_and_validate_buffered(&source.replace("", "PROGRAM")); + assert_snapshot!(diagnostics, @r###" + error[E032]: this POU takes 1 argument but 2 arguments were supplied + ┌─ :9:13 + │ + 9 │ one_instance(1, 2); + │ ^^^^^^^^^^^^ this POU takes 1 argument but 2 arguments were supplied + + error[E032]: this POU takes 2 arguments but 3 arguments were supplied + ┌─ :12:13 + │ + 12 │ two_instance(1, 2, 3); + │ ^^^^^^^^^^^^ this POU takes 2 arguments but 3 arguments were supplied + + error[E031]: Expected a reference for parameter out_two because their type is Output + ┌─ :12:29 + │ + 12 │ two_instance(1, 2, 3); + │ ^ Expected a reference for parameter out_two because their type is Output + + "###); +} From 1baf21956f97b52290880fb4724e1ad8f1490f6a Mon Sep 17 00:00:00 2001 From: Volkan Date: Wed, 5 Jun 2024 11:28:45 +0200 Subject: [PATCH 07/13] Update E032.md --- .../plc_diagnostics/src/diagnostics/error_codes/E032.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/plc_diagnostics/src/diagnostics/error_codes/E032.md b/compiler/plc_diagnostics/src/diagnostics/error_codes/E032.md index 2762d3526d..cb2b5ed020 100644 --- a/compiler/plc_diagnostics/src/diagnostics/error_codes/E032.md +++ b/compiler/plc_diagnostics/src/diagnostics/error_codes/E032.md @@ -13,6 +13,6 @@ END_FUNCTION ``` Note that for `FUNCTION`s the argument count must match with the parameter list and can be bigger if a variadic -parameter is present. For stateful POUs variadic parameters are not supported, thus the argument count must be equal or -less than the parameter list depending on whether optional arguments such as `VAR_INPUT` or `VAR_OUTPUT` were not -passed. \ No newline at end of file +parameter is present. For stateful POUs variadic parameters are not supported, thus the argument count must be equal +or less than the parameter list depending on whether optional arguments such as `VAR_INPUT` or `VAR_OUTPUT` were +passed or not. From bb3143c79f45388b036f692c0014f6e6418da8bc Mon Sep 17 00:00:00 2001 From: Volkan Date: Fri, 7 Jun 2024 12:01:59 +0200 Subject: [PATCH 08/13] Update src/index.rs Co-authored-by: Michael <78988079+mhasel@users.noreply.github.com> --- src/index.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.rs b/src/index.rs index 72fbd1a4c3..11be9a5d1a 100644 --- a/src/index.rs +++ b/src/index.rs @@ -1199,8 +1199,8 @@ impl Index { .collect::>() } - pub fn has_variadic_parameter(&self, pout_name: &str) -> bool { - self.get_pou_members(pout_name).iter().any(|member| member.is_parameter() && member.is_variadic()) + pub fn has_variadic_parameter(&self, pou_name: &str) -> bool { + self.get_pou_members(pou_name).iter().any(|member| member.is_parameter() && member.is_variadic()) } /// returns some if the current index is a VAR_INPUT, VAR_IN_OUT or VAR_OUTPUT that is not a variadic argument From b988b0b1606c5573f4b7943d87c23a33cd1923c4 Mon Sep 17 00:00:00 2001 From: Volkan Date: Fri, 7 Jun 2024 12:02:05 +0200 Subject: [PATCH 09/13] Update src/validation/statement.rs Co-authored-by: Michael <78988079+mhasel@users.noreply.github.com> --- src/validation/statement.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validation/statement.rs b/src/validation/statement.rs index 8c65b3fb17..a2d83a3500 100644 --- a/src/validation/statement.rs +++ b/src/validation/statement.rs @@ -1150,7 +1150,7 @@ fn validate_call( validate_argument_count(context, validator, pou, &arguments, &operator.location); } - let mut argument_are_implicit = true; + let mut arguments_are_implicit = true; let mut variable_location_in_parent = vec![]; // validate parameters From 6ab4421520a5366b2b4f0372b58975faa304b4db Mon Sep 17 00:00:00 2001 From: Volkan Date: Fri, 7 Jun 2024 12:02:09 +0200 Subject: [PATCH 10/13] Update src/validation/statement.rs Co-authored-by: Michael <78988079+mhasel@users.noreply.github.com> --- src/validation/statement.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/validation/statement.rs b/src/validation/statement.rs index a2d83a3500..14b85f6131 100644 --- a/src/validation/statement.rs +++ b/src/validation/statement.rs @@ -1174,8 +1174,8 @@ fn validate_call( // mixing implicit and explicit arguments is not allowed // allways compare to the first argument if i == 0 { - argument_are_implicit = is_implicit; - } else if argument_are_implicit != is_implicit { + arguments_are_implicit = is_implicit; + } else if arguments_are_implicit != is_implicit { validator.push_diagnostic( Diagnostic::new("Cannot mix implicit and explicit call parameters!") .with_error_code("E031") From 02a00ddd175fe73d70bf1b382a64911c55317973 Mon Sep 17 00:00:00 2001 From: Volkan Date: Fri, 7 Jun 2024 12:02:19 +0200 Subject: [PATCH 11/13] Update src/validation/statement.rs Co-authored-by: Michael <78988079+mhasel@users.noreply.github.com> --- src/validation/statement.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/validation/statement.rs b/src/validation/statement.rs index 14b85f6131..861ad2a616 100644 --- a/src/validation/statement.rs +++ b/src/validation/statement.rs @@ -1488,9 +1488,11 @@ fn validate_assignment_type_sizes( }); } -/// Validates if a POU call has the correct amount of arguments. Specifically for functions the -/// argument count must be greater or equal depending on if a variadic parameter is present whereas for -/// stateful POUs the argument count can be less since VAR_INPUT and VAR_OUTPUT arguments are optional +/// Validates if a POU call has the correct number of arguments. Specifically, for functions, +/// the argument count must be equal to the required count unless the interface is variadic, +/// in which case the argument count may be greater than or equal to the required count. For stateful +/// POUs, the argument count can be less than or equal to the required count since VAR_INPUT and +/// VAR_OUTPUT arguments are optional. fn validate_argument_count( context: &ValidationContext, validator: &mut Validator, From 20c1e68505fba7271a735a6c8fdd2a6b2cd32ecd Mon Sep 17 00:00:00 2001 From: Volkan Sagcan Date: Fri, 7 Jun 2024 12:06:32 +0200 Subject: [PATCH 12/13] feedback --- compiler/plc_diagnostics/src/diagnostics.rs | 5 +++-- ...builtins_called_with_invalid_param_count.snap | 4 ++-- ...builtins_called_with_invalid_param_count.snap | 4 ++-- ...ins_called_with_invalid_number_of_params.snap | 16 ++++++++-------- .../tests/statement_validation_tests.rs | 4 ++-- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/compiler/plc_diagnostics/src/diagnostics.rs b/compiler/plc_diagnostics/src/diagnostics.rs index c6fc5470a2..669ffa7b2e 100644 --- a/compiler/plc_diagnostics/src/diagnostics.rs +++ b/compiler/plc_diagnostics/src/diagnostics.rs @@ -215,9 +215,10 @@ impl Diagnostic { } Diagnostic::new(format!( - "this POU takes {expected} but {actual} were supplied", + "this POU takes {expected} but {actual} {was_or_were} supplied", expected = message(expected), - actual = message(actual) + actual = message(actual), + was_or_were = if actual == 1 { "was" } else { "were" } )) .with_error_code("E032") .with_location(location.into()) diff --git a/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__arithmetic_builtins_called_with_invalid_param_count.snap b/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__arithmetic_builtins_called_with_invalid_param_count.snap index 505f01eddb..f32c66c15d 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__arithmetic_builtins_called_with_invalid_param_count.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__arithmetic_builtins_called_with_invalid_param_count.snap @@ -14,11 +14,11 @@ error[E064]: Could not resolve generic type T with ANY_NUMBER 7 │ ADD(); │ ^^^^^^ Could not resolve generic type T with ANY_NUMBER -error[E032]: this POU takes 2 arguments but 1 argument were supplied +error[E032]: this POU takes 2 arguments but 1 argument was supplied ┌─ :8:13 │ 8 │ MUL(x1); - │ ^^^ this POU takes 2 arguments but 1 argument were supplied + │ ^^^ this POU takes 2 arguments but 1 argument was supplied error[E032]: this POU takes 2 arguments but 4 arguments were supplied ┌─ :9:13 diff --git a/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__comparison_builtins_called_with_invalid_param_count.snap b/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__comparison_builtins_called_with_invalid_param_count.snap index 492bcc0fd5..5eb779a4d0 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__comparison_builtins_called_with_invalid_param_count.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__builtin_validation_tests__comparison_builtins_called_with_invalid_param_count.snap @@ -8,11 +8,11 @@ error[E032]: this POU takes 2 arguments but 0 arguments were supplied 7 │ EQ(); │ ^^ this POU takes 2 arguments but 0 arguments were supplied -error[E032]: this POU takes 2 arguments but 1 argument were supplied +error[E032]: this POU takes 2 arguments but 1 argument was supplied ┌─ :8:13 │ 8 │ GT(x1); - │ ^^ this POU takes 2 arguments but 1 argument were supplied + │ ^^ this POU takes 2 arguments but 1 argument was supplied error[E032]: this POU takes 2 arguments but 4 arguments were supplied ┌─ :10:13 diff --git a/src/validation/tests/snapshots/rusty__validation__tests__variable_length_array_test__builtins__builtins_called_with_invalid_number_of_params.snap b/src/validation/tests/snapshots/rusty__validation__tests__variable_length_array_test__builtins__builtins_called_with_invalid_number_of_params.snap index b249f97e45..d2c0b22a83 100644 --- a/src/validation/tests/snapshots/rusty__validation__tests__variable_length_array_test__builtins__builtins_called_with_invalid_number_of_params.snap +++ b/src/validation/tests/snapshots/rusty__validation__tests__variable_length_array_test__builtins__builtins_called_with_invalid_number_of_params.snap @@ -8,17 +8,17 @@ error[E032]: this POU takes 2 arguments but 0 arguments were supplied 13 │ LOWER_BOUND(); │ ^^^^^^^^^^^ this POU takes 2 arguments but 0 arguments were supplied -error[E032]: this POU takes 2 arguments but 1 argument were supplied +error[E032]: this POU takes 2 arguments but 1 argument was supplied ┌─ :14:13 │ 14 │ LOWER_BOUND(vla); - │ ^^^^^^^^^^^ this POU takes 2 arguments but 1 argument were supplied + │ ^^^^^^^^^^^ this POU takes 2 arguments but 1 argument was supplied -error[E032]: this POU takes 2 arguments but 1 argument were supplied +error[E032]: this POU takes 2 arguments but 1 argument was supplied ┌─ :15:13 │ 15 │ LOWER_BOUND(1); - │ ^^^^^^^^^^^ this POU takes 2 arguments but 1 argument were supplied + │ ^^^^^^^^^^^ this POU takes 2 arguments but 1 argument was supplied error[E031]: Expected a reference for parameter arr because their type is InOut ┌─ :15:25 @@ -44,17 +44,17 @@ error[E032]: this POU takes 2 arguments but 0 arguments were supplied 18 │ UPPER_BOUND(); │ ^^^^^^^^^^^ this POU takes 2 arguments but 0 arguments were supplied -error[E032]: this POU takes 2 arguments but 1 argument were supplied +error[E032]: this POU takes 2 arguments but 1 argument was supplied ┌─ :19:13 │ 19 │ UPPER_BOUND(vla); - │ ^^^^^^^^^^^ this POU takes 2 arguments but 1 argument were supplied + │ ^^^^^^^^^^^ this POU takes 2 arguments but 1 argument was supplied -error[E032]: this POU takes 2 arguments but 1 argument were supplied +error[E032]: this POU takes 2 arguments but 1 argument was supplied ┌─ :20:13 │ 20 │ UPPER_BOUND(1); - │ ^^^^^^^^^^^ this POU takes 2 arguments but 1 argument were supplied + │ ^^^^^^^^^^^ this POU takes 2 arguments but 1 argument was supplied error[E031]: Expected a reference for parameter arr because their type is InOut ┌─ :20:25 diff --git a/src/validation/tests/statement_validation_tests.rs b/src/validation/tests/statement_validation_tests.rs index 1a873b3407..e2cc050b35 100644 --- a/src/validation/tests/statement_validation_tests.rs +++ b/src/validation/tests/statement_validation_tests.rs @@ -1722,11 +1722,11 @@ fn incorrect_argument_count_stateless_pous() { 4 │ fn_with_one_parameter(1, 2); │ ^^^^^^^^^^^^^^^^^^^^^ this POU takes 1 argument but 2 arguments were supplied - error[E032]: this POU takes 2 arguments but 1 argument were supplied + error[E032]: this POU takes 2 arguments but 1 argument was supplied ┌─ :6:13 │ 6 │ fn_with_two_parameters(1); - │ ^^^^^^^^^^^^^^^^^^^^^^ this POU takes 2 arguments but 1 argument were supplied + │ ^^^^^^^^^^^^^^^^^^^^^^ this POU takes 2 arguments but 1 argument was supplied error[E032]: this POU takes 2 arguments but 3 arguments were supplied ┌─ :7:13 From 65337487035d08927efd0ecf6d3da9c06e26872b Mon Sep 17 00:00:00 2001 From: Volkan Sagcan Date: Tue, 11 Jun 2024 09:41:56 +0200 Subject: [PATCH 13/13] fmt --- src/validation/statement.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validation/statement.rs b/src/validation/statement.rs index 861ad2a616..55266cc713 100644 --- a/src/validation/statement.rs +++ b/src/validation/statement.rs @@ -1491,7 +1491,7 @@ fn validate_assignment_type_sizes( /// Validates if a POU call has the correct number of arguments. Specifically, for functions, /// the argument count must be equal to the required count unless the interface is variadic, /// in which case the argument count may be greater than or equal to the required count. For stateful -/// POUs, the argument count can be less than or equal to the required count since VAR_INPUT and +/// POUs, the argument count can be less than or equal to the required count since VAR_INPUT and /// VAR_OUTPUT arguments are optional. fn validate_argument_count( context: &ValidationContext,