Treat singletons and arrays as subtypes rather than coercible (#7181)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
@ -14,7 +14,7 @@ use crate::{
|
||||
|
||||
/// Apply a function to each element of an array.
|
||||
pub async fn map(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let array: Vec<KclValue> = args.get_unlabeled_kw_arg("array")?;
|
||||
let array: Vec<KclValue> = args.get_unlabeled_kw_arg_typed("array", &RuntimeType::any_array(), exec_state)?;
|
||||
let f: &FunctionSource = args.get_kw_arg("f")?;
|
||||
let new_array = inner_map(array, f, exec_state, &args).await?;
|
||||
Ok(KclValue::HomArray {
|
||||
@ -68,7 +68,7 @@ async fn call_map_closure(
|
||||
|
||||
/// For each item in an array, update a value.
|
||||
pub async fn reduce(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let array: Vec<KclValue> = args.get_unlabeled_kw_arg("array")?;
|
||||
let array: Vec<KclValue> = args.get_unlabeled_kw_arg_typed("array", &RuntimeType::any_array(), exec_state)?;
|
||||
let f: &FunctionSource = args.get_kw_arg("f")?;
|
||||
let initial: KclValue = args.get_kw_arg("initial")?;
|
||||
inner_reduce(array, initial, f, exec_state, &args).await
|
||||
@ -126,61 +126,23 @@ async fn call_reduce_closure(
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
pub async fn push(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let array = args.get_unlabeled_kw_arg("array")?;
|
||||
pub async fn push(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (mut array, ty) = args.get_unlabeled_kw_arg_array_and_type("array", exec_state)?;
|
||||
let item: KclValue = args.get_kw_arg("item")?;
|
||||
|
||||
let KclValue::HomArray { value: values, ty } = array else {
|
||||
let meta = vec![args.source_range];
|
||||
let actual_type = array.human_friendly_type();
|
||||
return Err(KclError::Semantic(KclErrorDetails::new(
|
||||
format!("You can't push to a value of type {actual_type}, only an array"),
|
||||
meta,
|
||||
)));
|
||||
};
|
||||
let ty = if item.has_type(&ty) {
|
||||
ty
|
||||
} else {
|
||||
// The user pushed an item with a type that differs from the array's
|
||||
// element type.
|
||||
RuntimeType::any()
|
||||
};
|
||||
|
||||
let new_array = inner_push(values, item);
|
||||
|
||||
Ok(KclValue::HomArray { value: new_array, ty })
|
||||
}
|
||||
|
||||
fn inner_push(mut array: Vec<KclValue>, item: KclValue) -> Vec<KclValue> {
|
||||
array.push(item);
|
||||
array
|
||||
|
||||
Ok(KclValue::HomArray { value: array, ty })
|
||||
}
|
||||
|
||||
pub async fn pop(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let array = args.get_unlabeled_kw_arg("array")?;
|
||||
let KclValue::HomArray { value: values, ty } = array else {
|
||||
let meta = vec![args.source_range];
|
||||
let actual_type = array.human_friendly_type();
|
||||
return Err(KclError::Semantic(KclErrorDetails::new(
|
||||
format!("You can't pop from a value of type {actual_type}, only an array"),
|
||||
meta,
|
||||
)));
|
||||
};
|
||||
|
||||
let new_array = inner_pop(values, &args)?;
|
||||
Ok(KclValue::HomArray { value: new_array, ty })
|
||||
}
|
||||
|
||||
fn inner_pop(array: Vec<KclValue>, args: &Args) -> Result<Vec<KclValue>, KclError> {
|
||||
pub async fn pop(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (mut array, ty) = args.get_unlabeled_kw_arg_array_and_type("array", exec_state)?;
|
||||
if array.is_empty() {
|
||||
return Err(KclError::Semantic(KclErrorDetails::new(
|
||||
"Cannot pop from an empty array".to_string(),
|
||||
vec![args.source_range],
|
||||
)));
|
||||
}
|
||||
|
||||
// Create a new array with all elements except the last one
|
||||
let new_array = array[..array.len() - 1].to_vec();
|
||||
|
||||
Ok(new_array)
|
||||
array.pop();
|
||||
Ok(KclValue::HomArray { value: array, ty })
|
||||
}
|
||||
|
Reference in New Issue
Block a user