mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-02 22:54:36 +00:00
Start implementing some code that passes argument to functions and signals
This commit is contained in:
parent
a192ffe283
commit
a6504ee61b
6 changed files with 100 additions and 53 deletions
|
@ -58,6 +58,9 @@ struct SharedString
|
|||
return std::string_view(a) != std::string_view(b);
|
||||
}
|
||||
|
||||
friend std::ostream& operator<< (std::ostream& stream, const SharedString& shared_string) {
|
||||
return stream << std::string_view(shared_string);
|
||||
}
|
||||
private:
|
||||
/// Use SharedString::from_number
|
||||
explicit SharedString(double n) { cbindgen_private::sixtyfps_shared_string_from_number(this, n); }
|
||||
|
|
|
@ -233,6 +233,7 @@ pub enum Expression {
|
|||
/// A function call
|
||||
FunctionCall {
|
||||
function: Box<Expression>,
|
||||
arguments: Vec<Expression>,
|
||||
},
|
||||
|
||||
/// A SelfAssignment or an Assignment. When op is '=' this is a signel assignment.
|
||||
|
@ -335,7 +336,7 @@ impl Expression {
|
|||
}
|
||||
Expression::Cast { to, .. } => to.clone(),
|
||||
Expression::CodeBlock(sub) => sub.last().map_or(Type::Void, |e| e.ty()),
|
||||
Expression::FunctionCall { function } => function.ty(),
|
||||
Expression::FunctionCall { function, .. } => function.ty(),
|
||||
Expression::SelfAssignment { .. } => Type::Void,
|
||||
Expression::ResourceReference { .. } => Type::Resource,
|
||||
Expression::Condition { condition: _, true_expr, false_expr } => {
|
||||
|
@ -397,11 +398,12 @@ impl Expression {
|
|||
Expression::RepeaterModelReference { .. } => {}
|
||||
Expression::Cast { from, .. } => visitor(&**from),
|
||||
Expression::CodeBlock(sub) => {
|
||||
for e in sub {
|
||||
visitor(e)
|
||||
sub.iter().for_each(visitor);
|
||||
}
|
||||
Expression::FunctionCall { function, arguments } => {
|
||||
visitor(&**function);
|
||||
arguments.iter().for_each(visitor);
|
||||
}
|
||||
Expression::FunctionCall { function } => visitor(&**function),
|
||||
Expression::SelfAssignment { lhs, rhs, .. } => {
|
||||
visitor(&**lhs);
|
||||
visitor(&**rhs);
|
||||
|
@ -457,11 +459,12 @@ impl Expression {
|
|||
Expression::RepeaterModelReference { .. } => {}
|
||||
Expression::Cast { from, .. } => visitor(&mut **from),
|
||||
Expression::CodeBlock(sub) => {
|
||||
for e in sub {
|
||||
visitor(e)
|
||||
sub.iter_mut().for_each(visitor);
|
||||
}
|
||||
Expression::FunctionCall { function, arguments } => {
|
||||
visitor(&mut **function);
|
||||
arguments.iter_mut().for_each(visitor);
|
||||
}
|
||||
Expression::FunctionCall { function } => visitor(&mut **function),
|
||||
Expression::SelfAssignment { lhs, rhs, .. } => {
|
||||
visitor(&mut **lhs);
|
||||
visitor(&mut **rhs);
|
||||
|
@ -561,6 +564,7 @@ impl Expression {
|
|||
function: Box::new(Expression::BuiltinFunctionReference(
|
||||
BuiltinFunction::GetWindowScaleFactor,
|
||||
)),
|
||||
arguments: vec![],
|
||||
}),
|
||||
op: '/',
|
||||
},
|
||||
|
@ -570,6 +574,7 @@ impl Expression {
|
|||
function: Box::new(Expression::BuiltinFunctionReference(
|
||||
BuiltinFunction::GetWindowScaleFactor,
|
||||
)),
|
||||
arguments: vec![],
|
||||
}),
|
||||
op: '*',
|
||||
},
|
||||
|
|
|
@ -186,7 +186,7 @@ use crate::diagnostics::{BuildDiagnostics, CompilerDiagnostic, Level, Spanned};
|
|||
use crate::expression_tree::{BuiltinFunction, EasingCurve, Expression, ExpressionSpanned};
|
||||
use crate::layout::{gen::LayoutItemCodeGen, Layout, LayoutElement};
|
||||
use crate::object_tree::{Component, Element, ElementRc, RepeatedElementInfo};
|
||||
use crate::{parser::SyntaxNodeWithSourceFile, typeregister::Type};
|
||||
use crate::typeregister::Type;
|
||||
use cpp_ast::*;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
@ -944,18 +944,18 @@ fn compile_expression(e: &crate::expression_tree::Expression, component: &Rc<Com
|
|||
access_member(&element.upgrade().unwrap(), name.as_str(), component, "self");
|
||||
format!(r#"{}.get()"#, access)
|
||||
}
|
||||
Expression::SignalReference(NamedReference { element, name }) => {
|
||||
let access =
|
||||
access_member(&element.upgrade().unwrap(), name.as_str(), component, "self");
|
||||
format!(r#"{}.emit()"#, access)
|
||||
}
|
||||
Expression::SignalReference(NamedReference { element, name }) => format!(
|
||||
"{}.emit",
|
||||
access_member(&element.upgrade().unwrap(), name.as_str(), component, "self")
|
||||
),
|
||||
Expression::BuiltinFunctionReference(funcref) => match funcref {
|
||||
BuiltinFunction::GetWindowScaleFactor => {
|
||||
format!("{}.scale_factor()", window_ref_expression(component))
|
||||
format!("{}.scale_factor", window_ref_expression(component))
|
||||
}
|
||||
BuiltinFunction::Debug => {
|
||||
"[](auto... args){ (std::cout << ... << args) << std::endl; return nullptr; }"
|
||||
.into()
|
||||
}
|
||||
BuiltinFunction::Debug =>
|
||||
"[]{ std::cout << \"FIXME: the debug statement in C++ should print the argument\" << std::endl; return nullptr; }()".into()
|
||||
,
|
||||
},
|
||||
Expression::RepeaterIndexReference { element } => {
|
||||
let access = access_member(
|
||||
|
@ -975,7 +975,9 @@ fn compile_expression(e: &crate::expression_tree::Expression, component: &Rc<Com
|
|||
);
|
||||
format!(r#"{}model_data.get()"#, access)
|
||||
}
|
||||
Expression::FunctionParameterReference { index, .. } => format!("std::get<{}>(args)", index),
|
||||
Expression::FunctionParameterReference { index, .. } => {
|
||||
format!("std::get<{}>(args)", index)
|
||||
}
|
||||
Expression::StoreLocalVariable { name, value } => {
|
||||
format!("auto {} = {};", name, compile_expression(value, component))
|
||||
}
|
||||
|
@ -1010,12 +1012,10 @@ fn compile_expression(e: &crate::expression_tree::Expression, component: &Rc<Com
|
|||
|
||||
format!("[&]{{ {} }}()", x.join(";"))
|
||||
}
|
||||
Expression::FunctionCall { function } => {
|
||||
if matches!(function.ty(), Type::Signal{..} | Type::Function{..}) {
|
||||
compile_expression(&*function, component)
|
||||
} else {
|
||||
format!("\n#error the function `{:?}` is not a signal\n", function)
|
||||
}
|
||||
Expression::FunctionCall { function, arguments } => {
|
||||
let args =
|
||||
arguments.iter().map(|e| compile_expression(e, component)).collect::<Vec<_>>();
|
||||
format!("{}({})", compile_expression(&function, component), args.join(", "))
|
||||
}
|
||||
Expression::SelfAssignment { lhs, rhs, op } => match &**lhs {
|
||||
Expression::PropertyReference(NamedReference { element, name }) => {
|
||||
|
|
|
@ -112,7 +112,7 @@ fn generate_component(
|
|||
quote!(
|
||||
#[allow(dead_code)]
|
||||
pub fn #on_ident(self: ::core::pin::Pin<&Self>, f: impl Fn() + 'static) {
|
||||
Self::FIELD_OFFSETS.#prop_ident.apply_pin(self).set_handler(move |()|f())
|
||||
Self::FIELD_OFFSETS.#prop_ident.apply_pin(self).set_handler(move |_: &()|f())
|
||||
}
|
||||
)
|
||||
.into(),
|
||||
|
@ -704,11 +704,9 @@ fn compile_expression(e: &Expression, component: &Rc<Component>) -> TokenStream
|
|||
Expression::BuiltinFunctionReference(funcref) => match funcref {
|
||||
BuiltinFunction::GetWindowScaleFactor => {
|
||||
let window_ref = window_ref_expression(component);
|
||||
quote!(#window_ref.scale_factor())
|
||||
}
|
||||
BuiltinFunction::Debug => {
|
||||
quote!(println!("FIXME: the debug statement in rust should print the argument");)
|
||||
quote!(#window_ref.scale_factor)
|
||||
}
|
||||
BuiltinFunction::Debug => quote!((|x| println!("{:?}", x))),
|
||||
},
|
||||
Expression::RepeaterIndexReference { element } => {
|
||||
let access = access_member(
|
||||
|
@ -750,22 +748,20 @@ fn compile_expression(e: &Expression, component: &Rc<Component>) -> TokenStream
|
|||
let map = sub.iter().map(|e| compile_expression(e, &component));
|
||||
quote!({ #(#map);* })
|
||||
}
|
||||
Expression::SignalReference(NamedReference { element, name, .. }) => {
|
||||
let access = access_member(
|
||||
Expression::SignalReference(NamedReference { element, name, .. }) => access_member(
|
||||
&element.upgrade().unwrap(),
|
||||
name.as_str(),
|
||||
component,
|
||||
quote!(_self),
|
||||
false,
|
||||
);
|
||||
quote!(#access.emit(&()))
|
||||
}
|
||||
Expression::FunctionCall { function } => {
|
||||
if matches!(function.ty(), Type::Signal{..} | Type::Function{..}) {
|
||||
compile_expression(function, &component)
|
||||
),
|
||||
Expression::FunctionCall { function, arguments } => {
|
||||
let f = compile_expression(function, &component);
|
||||
let a = arguments.iter().map(|a| compile_expression(a, &component));
|
||||
if matches!(function.ty(), Type::Signal{..}) {
|
||||
quote! { #f.emit(&(#((#a).clone(),)*).into())}
|
||||
} else {
|
||||
let error = format!("the function {:?} is not a signal", e);
|
||||
quote!(compile_error! {#error})
|
||||
quote! { #f(#(#a.clone()),*)}
|
||||
}
|
||||
}
|
||||
Expression::SelfAssignment { lhs, rhs, op } => match &**lhs {
|
||||
|
|
|
@ -253,13 +253,7 @@ impl Expression {
|
|||
})
|
||||
})
|
||||
.or_else(|| {
|
||||
node.FunctionCallExpression().map(|n| Expression::FunctionCall {
|
||||
function: Box::new(
|
||||
n.child_node(SyntaxKind::Expression)
|
||||
.map(|n| Self::from_expression_node(n.into(), ctx))
|
||||
.unwrap_or(Expression::Invalid),
|
||||
),
|
||||
})
|
||||
node.FunctionCallExpression().map(|n| Self::from_function_call_node(n, ctx))
|
||||
})
|
||||
.or_else(|| node.SelfAssignment().map(|n| Self::from_self_assignement_node(n, ctx)))
|
||||
.or_else(|| node.BinaryExpression().map(|n| Self::from_binary_expression_node(n, ctx)))
|
||||
|
@ -470,6 +464,44 @@ impl Expression {
|
|||
Self::Invalid
|
||||
}
|
||||
|
||||
fn from_function_call_node(
|
||||
node: syntax_nodes::FunctionCallExpression,
|
||||
ctx: &mut LookupCtx,
|
||||
) -> Expression {
|
||||
let mut sub_expr =
|
||||
node.Expression().map(|n| (Self::from_expression_node(n.clone(), ctx), n));
|
||||
let function = Box::new(sub_expr.next().map_or(Expression::Invalid, |e| e.0));
|
||||
let arguments = sub_expr.collect::<Vec<_>>();
|
||||
|
||||
let arguments = match function.ty() {
|
||||
Type::Function { args, .. } | Type::Signal { args } => {
|
||||
if arguments.len() != args.len() {
|
||||
ctx.diag.push_error(
|
||||
format!(
|
||||
"The signal or function expects {} arguments, but {} are provided",
|
||||
args.len(),
|
||||
arguments.len()
|
||||
),
|
||||
&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, &mut ctx.diag))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
ctx.diag.push_error("The expression is not a function".into(), &node);
|
||||
arguments.into_iter().map(|x| x.0).collect()
|
||||
}
|
||||
};
|
||||
|
||||
Expression::FunctionCall { function, arguments }
|
||||
}
|
||||
|
||||
fn from_self_assignement_node(
|
||||
node: syntax_nodes::SelfAssignment,
|
||||
ctx: &mut LookupCtx,
|
||||
|
|
|
@ -18,6 +18,17 @@ Xxx := Rectangle {
|
|||
// ^error{Assignement need to be done on a property}
|
||||
width = x;
|
||||
// ^error{Cannot convert string to length}
|
||||
plop("hallo", #fff, 42);
|
||||
plop("hallo", #fff,);
|
||||
// ^error{The signal or function expects 3 arguments, but 2 are provided}
|
||||
plop("hallo", #fff, 42, true);
|
||||
// ^error{The signal or function expects 3 arguments, but 4 are provided}
|
||||
plop(42, 42, 42);
|
||||
// ^error{Cannot convert float to color}
|
||||
hello(45, fff)
|
||||
// ^error{The expression is not a function}
|
||||
// ^^error{Unknown unqualified identifier 'fff'}
|
||||
|
||||
}
|
||||
|
||||
x: 12px;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue