Merge the Callback and Function type

There is no need for two of these
This simplify some code

Amend efdecf0a13
This commit is contained in:
Olivier Goffart 2024-10-28 14:36:30 +01:00 committed by GitHub
parent dff19c52da
commit 6bb0e6038f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 72 additions and 135 deletions

View file

@ -160,18 +160,13 @@ impl JsComponentInstance {
}
};
if let Some(return_type) = &return_type {
if let Ok(value) = super::to_value(&env, result, return_type) {
return value;
} else {
eprintln!(
"Node.js: cannot convert return type of callback {}",
callback_name
);
return slint_interpreter::default_value_for_type(return_type);
}
} else {
if matches!(return_type, Type::Void) {
Value::Void
} else if let Ok(value) = super::to_value(&env, result, &return_type) {
return value;
} else {
eprintln!("Node.js: cannot convert return type of callback {callback_name}");
return slint_interpreter::default_value_for_type(&return_type);
}
}
})
@ -237,18 +232,13 @@ impl JsComponentInstance {
}
};
if let Some(return_type) = &return_type {
if let Ok(value) = super::to_value(&env, result, return_type) {
return value;
} else {
eprintln!(
"Node.js: cannot convert return type of callback {}",
callback_name
);
return slint_interpreter::default_value_for_type(return_type);
}
} else {
if matches!(return_type, Type::Void) {
Value::Void
} else if let Ok(value) = super::to_value(&env, result, &return_type) {
return value;
} else {
eprintln!("Node.js: cannot convert return type of callback {callback_name}");
return slint_interpreter::default_value_for_type(&return_type);
}
}
})
@ -306,10 +296,7 @@ impl JsComponentInstance {
})?;
let args = match ty {
Type::Callback(callback) => {
Self::invoke_args(env, &callback_name, arguments, &callback.args)?
}
Type::Function(function) => {
Type::Callback(function) | Type::Function(function) => {
Self::invoke_args(env, &callback_name, arguments, &function.args)?
}
_ => {
@ -352,10 +339,7 @@ impl JsComponentInstance {
})?;
let args = match ty {
Type::Callback(callback) => {
Self::invoke_args(env, &callback_name, arguments, &callback.args)?
}
Type::Function(function) => {
Type::Callback(function) | Type::Function(function) => {
Self::invoke_args(env, &callback_name, arguments, &function.args)?
}
_ => {

View file

@ -706,10 +706,7 @@ impl Expression {
Expression::Cast { to, .. } => to.clone(),
Expression::CodeBlock(sub) => sub.last().map_or(Type::Void, |e| e.ty()),
Expression::FunctionCall { function, .. } => match function.ty() {
Type::Function(function) => function.return_type.clone(),
Type::Callback(callback) => {
callback.return_type.as_ref().unwrap_or(&Type::Void).clone()
}
Type::Function(f) | Type::Callback(f) => f.return_type.clone(),
_ => Type::Invalid,
},
Expression::SelfAssignment { .. } => Type::Void,

View file

@ -626,7 +626,7 @@ fn handle_property_init(
code = return_compile_expression(
&binding_expression.expression.borrow(),
&ctx2,
callback.return_type.as_ref()
Some(&callback.return_type)
)
));
} else {
@ -1861,10 +1861,7 @@ fn generate_sub_component(
let ty = if let Type::Callback(callback) = &property.ty {
let param_types =
callback.args.iter().map(|t| t.cpp_type().unwrap()).collect::<Vec<_>>();
let return_type = callback
.return_type
.as_ref()
.map_or(SmolStr::new_static("void"), |t| t.cpp_type().unwrap());
let return_type = callback.return_type.cpp_type().unwrap();
format_smolstr!(
"slint::private_api::Callback<{}({})>",
return_type,
@ -2503,13 +2500,9 @@ fn generate_global(
let ty = if let Type::Callback(callback) = &property.ty {
let param_types =
callback.args.iter().map(|t| t.cpp_type().unwrap()).collect::<Vec<_>>();
let return_type = callback
.return_type
.as_ref()
.map_or(SmolStr::new_static("void"), |t| t.cpp_type().unwrap());
format_smolstr!(
"slint::private_api::Callback<{}({})>",
return_type,
callback.return_type.cpp_type().unwrap(),
param_types.join(", ")
)
} else {
@ -2640,8 +2633,6 @@ fn generate_public_api_for_properties(
if let Type::Callback(callback) = &p.ty {
let param_types =
callback.args.iter().map(|t| t.cpp_type().unwrap()).collect::<Vec<_>>();
let return_type =
callback.return_type.as_ref().map_or("void".into(), |t| t.cpp_type().unwrap());
let callback_emitter = vec![
"[[maybe_unused]] auto self = this;".into(),
format!(
@ -2661,7 +2652,7 @@ fn generate_public_api_for_properties(
.enumerate()
.map(|(i, ty)| format!("{} arg_{}", ty, i))
.join(", "),
return_type
callback.return_type.cpp_type().unwrap()
),
statements: Some(callback_emitter),
..Default::default()

View file

@ -466,11 +466,7 @@ fn handle_property_init(
ctx2.argument_types = &callback.args;
let tokens_for_expression =
compile_expression(&binding_expression.expression.borrow(), &ctx2);
let as_ = if callback.return_type.as_ref().map_or(true, |t| matches!(t, Type::Void)) {
quote!(;)
} else {
quote!(as _)
};
let as_ = if matches!(callback.return_type, Type::Void) { quote!(;) } else { quote!(as _) };
init.push(quote!({
#[allow(unreachable_code, unused)]
slint::private_unstable_api::set_callback_handler(#rust_property, &self_rc, {
@ -553,10 +549,7 @@ fn public_api(
if let Type::Callback(callback) = &p.ty {
let callback_args =
callback.args.iter().map(|a| rust_primitive_type(a).unwrap()).collect::<Vec<_>>();
let return_type = callback
.return_type
.as_ref()
.map_or(quote!(()), |a| rust_primitive_type(a).unwrap());
let return_type = rust_primitive_type(&callback.return_type).unwrap();
let args_name =
(0..callback.args.len()).map(|i| format_ident!("arg_{}", i)).collect::<Vec<_>>();
let caller_ident = format_ident!("invoke_{}", prop_ident);
@ -684,10 +677,7 @@ fn generate_sub_component(
if let Type::Callback(callback) = &property.ty {
let callback_args =
callback.args.iter().map(|a| rust_primitive_type(a).unwrap()).collect::<Vec<_>>();
let return_type = callback
.return_type
.as_ref()
.map_or(quote!(()), |a| rust_primitive_type(a).unwrap());
let return_type = rust_primitive_type(&callback.return_type).unwrap();
declared_callbacks.push(prop_ident.clone());
declared_callbacks_types.push(callback_args);
declared_callbacks_ret.push(return_type);
@ -1312,10 +1302,7 @@ fn generate_global(global: &llr::GlobalComponent, root: &llr::CompilationUnit) -
if let Type::Callback(callback) = &property.ty {
let callback_args =
callback.args.iter().map(|a| rust_primitive_type(a).unwrap()).collect::<Vec<_>>();
let return_type = callback
.return_type
.as_ref()
.map_or(quote!(()), |a| rust_primitive_type(a).unwrap());
let return_type = rust_primitive_type(&callback.return_type);
declared_callbacks.push(prop_ident.clone());
declared_callbacks_types.push(callback_args);
declared_callbacks_ret.push(return_type);

View file

@ -27,7 +27,7 @@ pub enum Type {
/// The type of a callback alias whose type was not yet inferred
InferredCallback,
Callback(Rc<Callback>),
Callback(Rc<Function>),
Function(Rc<Function>),
ComponentFactory,
@ -127,9 +127,7 @@ impl Display for Type {
}
write!(f, ")")?
}
if let Some(rt) = &callback.return_type {
write!(f, "-> {}", rt)?;
}
write!(f, "-> {}", callback.return_type)?;
Ok(())
}
Type::ComponentFactory => write!(f, "component-factory"),
@ -782,12 +780,6 @@ impl<'a> PropertyLookupResult<'a> {
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Callback {
pub return_type: Option<Type>,
pub args: Vec<Type>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Function {
pub return_type: Type,

View file

@ -273,7 +273,7 @@ impl Expression {
},
Self::CallBackCall { callback, .. } => {
if let Type::Callback(callback) = ctx.property_ty(callback) {
callback.return_type.as_ref().unwrap_or(&Type::Void).clone()
callback.return_type.clone()
} else {
Type::Invalid
}

View file

@ -12,8 +12,8 @@ use std::rc::Rc;
use crate::expression_tree::{BuiltinFunction, Expression};
use crate::langtype::{
BuiltinElement, BuiltinPropertyDefault, BuiltinPropertyInfo, Callback, DefaultSizeBinding,
ElementType, NativeClass, Type,
BuiltinElement, BuiltinPropertyDefault, BuiltinPropertyInfo, DefaultSizeBinding, ElementType,
Function, NativeClass, Type,
};
use crate::object_tree::{self, *};
use crate::parser::{identifier_text, syntax_nodes, SyntaxKind, SyntaxNode};
@ -103,7 +103,7 @@ pub(crate) fn load_builtins(register: &mut TypeRegister) {
.chain(e.CallbackDeclaration().map(|s| {
(
identifier_text(&s.DeclaredIdentifier()).unwrap(),
BuiltinPropertyInfo::new(Type::Callback(Rc::new(Callback{
BuiltinPropertyInfo::new(Type::Callback(Rc::new(Function{
args: s
.CallbackDeclarationParameter()
.map(|a| {
@ -116,7 +116,7 @@ pub(crate) fn load_builtins(register: &mut TypeRegister) {
*diag.borrow_mut(),
register,
)
}),
}).unwrap_or(Type::Void),
}))),
)
}))

View file

@ -65,8 +65,7 @@ impl<'a> LookupCtx<'a> {
pub fn return_type(&self) -> &Type {
match &self.property_type {
Type::Callback(callback) => callback.return_type.as_ref().unwrap_or(&Type::Void),
Type::Function(function) => &function.return_type,
Type::Callback(f) | Type::Function(f) => &f.return_type,
_ => &self.property_type,
}
}
@ -194,8 +193,7 @@ impl LookupObject for ArgumentsLookup {
f: &mut impl FnMut(&str, LookupResult) -> Option<R>,
) -> Option<R> {
let args = match &ctx.property_type {
Type::Callback(callback) => &callback.args,
Type::Function(function) => &function.args,
Type::Callback(f) | Type::Function(f) => &f.args,
_ => return None,
};
for (index, (name, ty)) in ctx.arguments.iter().zip(args.iter()).enumerate() {

View file

@ -9,10 +9,9 @@
use crate::diagnostics::{BuildDiagnostics, SourceLocation, Spanned};
use crate::expression_tree::{self, BindingExpression, Expression, Unit};
use crate::langtype::EnumerationValue;
use crate::langtype::{
BuiltinElement, BuiltinPropertyDefault, Callback, Enumeration, Function, NativeClass, Struct,
Type,
BuiltinElement, BuiltinPropertyDefault, Enumeration, EnumerationValue, Function, NativeClass,
Struct, Type,
};
use crate::langtype::{ElementType, PropertyLookupResult};
use crate::layout::{LayoutConstraints, Orientation};
@ -1156,12 +1155,14 @@ impl Element {
}
type_from_node(p.Type(), diag, tr)})
.collect();
let return_type =
sig_decl.ReturnType().map(|ret_ty| type_from_node(ret_ty.Type(), diag, tr));
let return_type = sig_decl
.ReturnType()
.map(|ret_ty| type_from_node(ret_ty.Type(), diag, tr))
.unwrap_or(Type::Void);
r.property_declarations.insert(
name,
PropertyDeclaration {
property_type: Type::Callback(Rc::new(Callback { return_type, args })),
property_type: Type::Callback(Rc::new(Function { return_type, args })),
node: Some(sig_decl.into()),
visibility: PropertyVisibility::InOut,
pure,

View file

@ -91,15 +91,7 @@ fn visit_declared_type(ty: &Type, visitor: &mut impl FnMut(&SmolStr, &Type)) {
}
}
Type::Array(x) => visit_declared_type(x, visitor),
Type::Callback(callback) => {
if let Some(rt) = &callback.return_type {
visit_declared_type(rt, visitor);
}
for a in &callback.args {
visit_declared_type(a, visitor);
}
}
Type::Function(function) => {
Type::Function(function) | Type::Callback(function) => {
visit_declared_type(&function.return_type, visitor);
for a in &function.args {
visit_declared_type(a, visitor);

View file

@ -943,30 +943,26 @@ impl Expression {
};
arguments.extend(sub_expr);
let mut handle_args = |arguments: Vec<(Expression, Option<NodeOrToken>)>,
args: &Vec<Type>| {
if arguments.len() != args.len() {
ctx.diag.push_error(
format!(
"The callback or function expects {} arguments, but {} are provided",
args.len() - adjust_arg_count,
arguments.len() - adjust_arg_count,
),
&node,
);
arguments.into_iter().map(|x| x.0).collect()
} else {
arguments
.into_iter()
.zip(args.iter())
.map(|((e, node), ty)| e.maybe_convert_to(ty.clone(), &node, ctx.diag))
.collect()
}
};
let arguments = match function.ty() {
Type::Function(function) => handle_args(arguments, &function.args),
Type::Callback(callback) => handle_args(arguments, &callback.args),
Type::Function(function) | Type::Callback(function) => {
if arguments.len() != function.args.len() {
ctx.diag.push_error(
format!(
"The callback or function expects {} arguments, but {} are provided",
function.args.len() - adjust_arg_count,
arguments.len() - adjust_arg_count,
),
&node,
);
arguments.into_iter().map(|x| x.0).collect()
} else {
arguments
.into_iter()
.zip(function.args.iter())
.map(|((e, node), ty)| e.maybe_convert_to(ty.clone(), &node, ctx.diag))
.collect()
}
}
Type::Invalid => {
debug_assert!(ctx.diag.has_errors());
arguments.into_iter().map(|x| x.0).collect()

View file

@ -10,8 +10,8 @@ use std::rc::Rc;
use crate::expression_tree::BuiltinFunction;
use crate::langtype::{
BuiltinElement, BuiltinPropertyDefault, BuiltinPropertyInfo, Callback, ElementType,
Enumeration, PropertyLookupResult, Struct, Type,
BuiltinElement, BuiltinPropertyDefault, BuiltinPropertyInfo, ElementType, Enumeration,
Function, PropertyLookupResult, Struct, Type,
};
use crate::object_tree::{Component, PropertyVisibility};
use crate::typeloader;
@ -128,12 +128,12 @@ impl BuiltinTypes {
node: None,
rust_attributes: None,
})),
noarg_callback_type: Type::Callback(Rc::new(Callback {
return_type: None,
noarg_callback_type: Type::Callback(Rc::new(Function {
return_type: Type::Void,
args: vec![],
})),
strarg_callback_type: Type::Callback(Rc::new(Callback {
return_type: None,
strarg_callback_type: Type::Callback(Rc::new(Function {
return_type: Type::Void,
args: vec![Type::String],
})),
layout_info_type: layout_info_type.clone(),

View file

@ -1485,7 +1485,7 @@ pub(crate) fn invoke_callback(
// If the callback was not set, the return value will be Value::Void, but we need
// to make sure that the value is actually of the right type as returned by the
// callback, otherwise we will get panics later
default_value_for_type(callback.return_type.as_ref().unwrap_or(&Type::Void))
default_value_for_type(&callback.return_type)
} else {
res
});

View file

@ -52,17 +52,16 @@ pub fn get_tooltip(document_cache: &mut DocumentCache, token: SyntaxToken) -> Op
}
fn from_prop_result(prop_info: PropertyLookupResult) -> Option<MarkupContent> {
let ret_ty =
|ty: &Type| if matches!(ty, Type::Void) { String::new() } else { format!(" -> {}", ty) };
let pure = if prop_info.declared_pure.is_some_and(|x| x) { "pure " } else { "" };
if let Type::Callback(callback) = &prop_info.property_type {
let ret = callback.return_type.as_ref().map(|x| format!(" -> {}", x)).unwrap_or_default();
let ret = ret_ty(&callback.return_type);
let args = callback.args.iter().map(|x| x.to_string()).join(", ");
Some(from_slint_code(&format!("{pure}callback {}({args}){ret}", prop_info.resolved_name)))
} else if let Type::Function(function) = &prop_info.property_type {
let ret = if matches!(function.return_type, Type::Void) {
String::new()
} else {
format!(" -> {}", function.return_type)
};
let ret = ret_ty(&function.return_type);
let args = function.args.iter().map(|x| x.to_string()).join(", ");
Some(from_slint_code(&format!("{pure}function {}({args}){ret}", prop_info.resolved_name)))
} else if prop_info.property_type.is_property_type() {

View file

@ -34,7 +34,7 @@ pub(crate) fn fold_node(
if lk.declared_pure == Some(true) {
write!(file, "pure ")?;
} else if let Type::Callback(callback) = lk.property_type {
if callback.return_type.is_some() {
if !matches!(callback.return_type, Type::Void) {
write!(file, "pure ")?;
}
}