Skip to content

Commit 289e146

Browse files
committed
Coerce the result of a function call to the function's return type
Signed-off-by: Nick Cameron <[email protected]>
1 parent 160f55e commit 289e146

File tree

1 file changed

+36
-2
lines changed

1 file changed

+36
-2
lines changed

rust/kcl-lib/src/execution/exec_ast.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2164,6 +2164,34 @@ fn assign_args_to_params_kw(
21642164
Ok(())
21652165
}
21662166

2167+
fn coerce_result_type(
2168+
result: Result<Option<KclValue>, KclError>,
2169+
function_expression: NodeRef<'_, FunctionExpression>,
2170+
exec_state: &mut ExecState,
2171+
) -> Result<Option<KclValue>, KclError> {
2172+
if let Ok(Some(val)) = result {
2173+
if let Some(ret_ty) = &function_expression.return_type {
2174+
let ty = RuntimeType::from_parsed(ret_ty.inner.clone(), exec_state, ret_ty.as_source_range())
2175+
.map_err(|e| KclError::Semantic(e.into()))?;
2176+
let val = val.coerce(&ty, exec_state).map_err(|_| {
2177+
KclError::Semantic(KclErrorDetails {
2178+
message: format!(
2179+
"This function requires its result to be of type `{}`, but found {}",
2180+
ty.human_friendly_type(),
2181+
val.human_friendly_type(),
2182+
),
2183+
source_ranges: ret_ty.as_source_ranges(),
2184+
})
2185+
})?;
2186+
Ok(Some(val))
2187+
} else {
2188+
Ok(Some(val))
2189+
}
2190+
} else {
2191+
result
2192+
}
2193+
}
2194+
21672195
async fn call_user_defined_function(
21682196
args: Vec<Arg>,
21692197
memory: EnvironmentRef,
@@ -2184,13 +2212,16 @@ async fn call_user_defined_function(
21842212
let result = ctx
21852213
.exec_block(&function_expression.body, exec_state, BodyType::Block)
21862214
.await;
2187-
let result = result.map(|_| {
2215+
let mut result = result.map(|_| {
21882216
exec_state
21892217
.stack()
21902218
.get(memory::RETURN_NAME, function_expression.as_source_range())
21912219
.ok()
21922220
.cloned()
21932221
});
2222+
2223+
result = coerce_result_type(result, function_expression, exec_state);
2224+
21942225
// Restore the previous memory.
21952226
exec_state.mut_stack().pop_env();
21962227

@@ -2218,13 +2249,16 @@ async fn call_user_defined_function_kw(
22182249
let result = ctx
22192250
.exec_block(&function_expression.body, exec_state, BodyType::Block)
22202251
.await;
2221-
let result = result.map(|_| {
2252+
let mut result = result.map(|_| {
22222253
exec_state
22232254
.stack()
22242255
.get(memory::RETURN_NAME, function_expression.as_source_range())
22252256
.ok()
22262257
.cloned()
22272258
});
2259+
2260+
result = coerce_result_type(result, function_expression, exec_state);
2261+
22282262
// Restore the previous memory.
22292263
exec_state.mut_stack().pop_env();
22302264

0 commit comments

Comments
 (0)