From 8838a34e07d22deb59439510235edf9306bd78a8 Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Sun, 10 Nov 2024 15:18:34 -0600 Subject: [PATCH] use generic version of value for param types --- libs/sqf/src/analyze/inspector/commands.rs | 7 +++-- .../analyze/inspector/external_functions.rs | 2 ++ libs/sqf/src/analyze/inspector/game_value.rs | 29 ++++++++++++------- libs/sqf/src/analyze/inspector/mod.rs | 1 + libs/sqf/tests/inspector/test_1.sqf | 5 ++++ 5 files changed, 32 insertions(+), 12 deletions(-) diff --git a/libs/sqf/src/analyze/inspector/commands.rs b/libs/sqf/src/analyze/inspector/commands.rs index 00208f1e..d955339f 100644 --- a/libs/sqf/src/analyze/inspector/commands.rs +++ b/libs/sqf/src/analyze/inspector/commands.rs @@ -1,3 +1,5 @@ +//! Emulates engine commands + use std::{collections::HashSet, ops::Range}; use crate::{analyze::inspector::VarSource, parser::database::Database, Expression}; @@ -86,7 +88,7 @@ impl SciptScope { for type_p in &arg_array[2] { if let GameValue::Array(Some(type_array)) = type_p { for type_i in type_array { - var_types.extend(type_i.iter().cloned()); + var_types.extend(type_i.iter().map(GameValue::make_generic)); } } } @@ -95,7 +97,8 @@ impl SciptScope { var_types.insert(GameValue::Anything); } // Add the default value to types - // It should be possible to move this above the is_empty check but not always safe + // It would be nice to move this above the is_empty check but not always safe + // ie: assume `params ["_z", ""]` is type string, but this is not guarentted if arg_array.len() > 1 && !arg_array[1].is_empty() { var_types.insert(arg_array[1][0].clone()); } diff --git a/libs/sqf/src/analyze/inspector/external_functions.rs b/libs/sqf/src/analyze/inspector/external_functions.rs index e7d6f1cb..a70b7e5a 100644 --- a/libs/sqf/src/analyze/inspector/external_functions.rs +++ b/libs/sqf/src/analyze/inspector/external_functions.rs @@ -1,3 +1,5 @@ +//! Emulate how common external functions will handle code + use std::collections::HashSet; use crate::{analyze::inspector::VarSource, parser::database::Database, Expression}; diff --git a/libs/sqf/src/analyze/inspector/game_value.rs b/libs/sqf/src/analyze/inspector/game_value.rs index 5a3e29e0..aa3fa805 100644 --- a/libs/sqf/src/analyze/inspector/game_value.rs +++ b/libs/sqf/src/analyze/inspector/game_value.rs @@ -1,3 +1,5 @@ +//! Game Values and mapping them from commands + use std::collections::HashSet; use arma3_wiki::model::{Arg, Call, Param, Value}; @@ -129,7 +131,7 @@ impl GameValue { "inAreaArray", ]; if !WIKI_CMDS_IGNORE_MISSING_PARAM.contains(&cmd_name) { - warn!("cmd {cmd_name} - param {name} not found"); + // warn!("cmd {cmd_name} - param {name} not found"); } return true; }; @@ -146,7 +148,7 @@ impl GameValue { return true; } - let test = set.iter().any(|s| { + set.iter().any(|s| { match s { Self::Anything | Self::Array(None) => { // println!("array (any/generic) pass"); @@ -154,9 +156,7 @@ impl GameValue { } Self::Array(Some(gv_array)) => { // println!("array (gv: {}) expected (arg: {})", gv_array.len(), arg_array.len()); - // if gv_array.len() > arg_array.len() { - // not really an error, some syntaxes take more than others - // } + // note: some syntaxes take more than others for (index, arg) in arg_array.iter().enumerate() { let possible = if index < gv_array.len() { gv_array[index].iter().cloned().collect() @@ -171,9 +171,7 @@ impl GameValue { } _ => false, } - }); - - test + }) } } } @@ -190,7 +188,6 @@ impl GameValue { #[must_use] /// matches values are compatible (Anything will always match) - /// todo: think about how nil and any interact? pub fn match_values(left: &Self, right: &Self) -> bool { if matches!(left, Self::Anything) { return true; @@ -247,7 +244,19 @@ impl GameValue { } } } - + #[must_use] + /// Gets a generic version of a type + pub fn make_generic(&self) -> Self { + match self { + Self::Array(_) => Self::Array(None), + Self::Boolean(_) => Self::Boolean(None), + Self::Code(_) => Self::Code(None), + Self::ForType(_) => Self::ForType(None), + Self::Number(_) => Self::Number(None), + Self::String(_) => Self::String(None), + _ => self.clone() + } + } #[must_use] /// Get as a string for debugging pub fn as_debug(&self) -> String { diff --git a/libs/sqf/src/analyze/inspector/mod.rs b/libs/sqf/src/analyze/inspector/mod.rs index bd113503..8add67d6 100644 --- a/libs/sqf/src/analyze/inspector/mod.rs +++ b/libs/sqf/src/analyze/inspector/mod.rs @@ -328,6 +328,7 @@ impl SciptScope { } "do" => { // from While, With, For, and Switch + // todo: handle switch return value Some(self.cmd_b_do(&lhs_set, &rhs_set, database)) } "from" | "to" | "step" => Some(self.cmd_b_from_chain(&lhs_set, &rhs_set)), diff --git a/libs/sqf/tests/inspector/test_1.sqf b/libs/sqf/tests/inspector/test_1.sqf index 4f7ad86a..d83115a9 100644 --- a/libs/sqf/tests/inspector/test_1.sqf +++ b/libs/sqf/tests/inspector/test_1.sqf @@ -125,3 +125,8 @@ call _varO; params [["_someString", "abc", [""]], ["_someCode", { 60 setGusts _someString }]]; call _someCode; // InvalidArgs for setGusts + +// ensure we use a generic version of the array param types or format would have an error +params [["_varP", "", ["", []]]]; +format _varP; +