mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-28 21:04:47 +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);
|
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:
|
private:
|
||||||
/// Use SharedString::from_number
|
/// Use SharedString::from_number
|
||||||
explicit SharedString(double n) { cbindgen_private::sixtyfps_shared_string_from_number(this, n); }
|
explicit SharedString(double n) { cbindgen_private::sixtyfps_shared_string_from_number(this, n); }
|
||||||
|
|
|
@ -233,6 +233,7 @@ pub enum Expression {
|
||||||
/// A function call
|
/// A function call
|
||||||
FunctionCall {
|
FunctionCall {
|
||||||
function: Box<Expression>,
|
function: Box<Expression>,
|
||||||
|
arguments: Vec<Expression>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// A SelfAssignment or an Assignment. When op is '=' this is a signel assignment.
|
/// 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::Cast { to, .. } => to.clone(),
|
||||||
Expression::CodeBlock(sub) => sub.last().map_or(Type::Void, |e| e.ty()),
|
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::SelfAssignment { .. } => Type::Void,
|
||||||
Expression::ResourceReference { .. } => Type::Resource,
|
Expression::ResourceReference { .. } => Type::Resource,
|
||||||
Expression::Condition { condition: _, true_expr, false_expr } => {
|
Expression::Condition { condition: _, true_expr, false_expr } => {
|
||||||
|
@ -397,11 +398,12 @@ impl Expression {
|
||||||
Expression::RepeaterModelReference { .. } => {}
|
Expression::RepeaterModelReference { .. } => {}
|
||||||
Expression::Cast { from, .. } => visitor(&**from),
|
Expression::Cast { from, .. } => visitor(&**from),
|
||||||
Expression::CodeBlock(sub) => {
|
Expression::CodeBlock(sub) => {
|
||||||
for e in sub {
|
sub.iter().for_each(visitor);
|
||||||
visitor(e)
|
|
||||||
}
|
}
|
||||||
|
Expression::FunctionCall { function, arguments } => {
|
||||||
|
visitor(&**function);
|
||||||
|
arguments.iter().for_each(visitor);
|
||||||
}
|
}
|
||||||
Expression::FunctionCall { function } => visitor(&**function),
|
|
||||||
Expression::SelfAssignment { lhs, rhs, .. } => {
|
Expression::SelfAssignment { lhs, rhs, .. } => {
|
||||||
visitor(&**lhs);
|
visitor(&**lhs);
|
||||||
visitor(&**rhs);
|
visitor(&**rhs);
|
||||||
|
@ -457,11 +459,12 @@ impl Expression {
|
||||||
Expression::RepeaterModelReference { .. } => {}
|
Expression::RepeaterModelReference { .. } => {}
|
||||||
Expression::Cast { from, .. } => visitor(&mut **from),
|
Expression::Cast { from, .. } => visitor(&mut **from),
|
||||||
Expression::CodeBlock(sub) => {
|
Expression::CodeBlock(sub) => {
|
||||||
for e in sub {
|
sub.iter_mut().for_each(visitor);
|
||||||
visitor(e)
|
|
||||||
}
|
}
|
||||||
|
Expression::FunctionCall { function, arguments } => {
|
||||||
|
visitor(&mut **function);
|
||||||
|
arguments.iter_mut().for_each(visitor);
|
||||||
}
|
}
|
||||||
Expression::FunctionCall { function } => visitor(&mut **function),
|
|
||||||
Expression::SelfAssignment { lhs, rhs, .. } => {
|
Expression::SelfAssignment { lhs, rhs, .. } => {
|
||||||
visitor(&mut **lhs);
|
visitor(&mut **lhs);
|
||||||
visitor(&mut **rhs);
|
visitor(&mut **rhs);
|
||||||
|
@ -561,6 +564,7 @@ impl Expression {
|
||||||
function: Box::new(Expression::BuiltinFunctionReference(
|
function: Box::new(Expression::BuiltinFunctionReference(
|
||||||
BuiltinFunction::GetWindowScaleFactor,
|
BuiltinFunction::GetWindowScaleFactor,
|
||||||
)),
|
)),
|
||||||
|
arguments: vec![],
|
||||||
}),
|
}),
|
||||||
op: '/',
|
op: '/',
|
||||||
},
|
},
|
||||||
|
@ -570,6 +574,7 @@ impl Expression {
|
||||||
function: Box::new(Expression::BuiltinFunctionReference(
|
function: Box::new(Expression::BuiltinFunctionReference(
|
||||||
BuiltinFunction::GetWindowScaleFactor,
|
BuiltinFunction::GetWindowScaleFactor,
|
||||||
)),
|
)),
|
||||||
|
arguments: vec![],
|
||||||
}),
|
}),
|
||||||
op: '*',
|
op: '*',
|
||||||
},
|
},
|
||||||
|
|
|
@ -186,7 +186,7 @@ use crate::diagnostics::{BuildDiagnostics, CompilerDiagnostic, Level, Spanned};
|
||||||
use crate::expression_tree::{BuiltinFunction, EasingCurve, Expression, ExpressionSpanned};
|
use crate::expression_tree::{BuiltinFunction, EasingCurve, Expression, ExpressionSpanned};
|
||||||
use crate::layout::{gen::LayoutItemCodeGen, Layout, LayoutElement};
|
use crate::layout::{gen::LayoutItemCodeGen, Layout, LayoutElement};
|
||||||
use crate::object_tree::{Component, Element, ElementRc, RepeatedElementInfo};
|
use crate::object_tree::{Component, Element, ElementRc, RepeatedElementInfo};
|
||||||
use crate::{parser::SyntaxNodeWithSourceFile, typeregister::Type};
|
use crate::typeregister::Type;
|
||||||
use cpp_ast::*;
|
use cpp_ast::*;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
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");
|
access_member(&element.upgrade().unwrap(), name.as_str(), component, "self");
|
||||||
format!(r#"{}.get()"#, access)
|
format!(r#"{}.get()"#, access)
|
||||||
}
|
}
|
||||||
Expression::SignalReference(NamedReference { element, name }) => {
|
Expression::SignalReference(NamedReference { element, name }) => format!(
|
||||||
let access =
|
"{}.emit",
|
||||||
access_member(&element.upgrade().unwrap(), name.as_str(), component, "self");
|
access_member(&element.upgrade().unwrap(), name.as_str(), component, "self")
|
||||||
format!(r#"{}.emit()"#, access)
|
),
|
||||||
}
|
|
||||||
Expression::BuiltinFunctionReference(funcref) => match funcref {
|
Expression::BuiltinFunctionReference(funcref) => match funcref {
|
||||||
BuiltinFunction::GetWindowScaleFactor => {
|
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 } => {
|
Expression::RepeaterIndexReference { element } => {
|
||||||
let access = access_member(
|
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)
|
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 } => {
|
Expression::StoreLocalVariable { name, value } => {
|
||||||
format!("auto {} = {};", name, compile_expression(value, component))
|
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(";"))
|
format!("[&]{{ {} }}()", x.join(";"))
|
||||||
}
|
}
|
||||||
Expression::FunctionCall { function } => {
|
Expression::FunctionCall { function, arguments } => {
|
||||||
if matches!(function.ty(), Type::Signal{..} | Type::Function{..}) {
|
let args =
|
||||||
compile_expression(&*function, component)
|
arguments.iter().map(|e| compile_expression(e, component)).collect::<Vec<_>>();
|
||||||
} else {
|
format!("{}({})", compile_expression(&function, component), args.join(", "))
|
||||||
format!("\n#error the function `{:?}` is not a signal\n", function)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Expression::SelfAssignment { lhs, rhs, op } => match &**lhs {
|
Expression::SelfAssignment { lhs, rhs, op } => match &**lhs {
|
||||||
Expression::PropertyReference(NamedReference { element, name }) => {
|
Expression::PropertyReference(NamedReference { element, name }) => {
|
||||||
|
|
|
@ -112,7 +112,7 @@ fn generate_component(
|
||||||
quote!(
|
quote!(
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn #on_ident(self: ::core::pin::Pin<&Self>, f: impl Fn() + 'static) {
|
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(),
|
.into(),
|
||||||
|
@ -704,11 +704,9 @@ fn compile_expression(e: &Expression, component: &Rc<Component>) -> TokenStream
|
||||||
Expression::BuiltinFunctionReference(funcref) => match funcref {
|
Expression::BuiltinFunctionReference(funcref) => match funcref {
|
||||||
BuiltinFunction::GetWindowScaleFactor => {
|
BuiltinFunction::GetWindowScaleFactor => {
|
||||||
let window_ref = window_ref_expression(component);
|
let window_ref = window_ref_expression(component);
|
||||||
quote!(#window_ref.scale_factor())
|
quote!(#window_ref.scale_factor)
|
||||||
}
|
|
||||||
BuiltinFunction::Debug => {
|
|
||||||
quote!(println!("FIXME: the debug statement in rust should print the argument");)
|
|
||||||
}
|
}
|
||||||
|
BuiltinFunction::Debug => quote!((|x| println!("{:?}", x))),
|
||||||
},
|
},
|
||||||
Expression::RepeaterIndexReference { element } => {
|
Expression::RepeaterIndexReference { element } => {
|
||||||
let access = access_member(
|
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));
|
let map = sub.iter().map(|e| compile_expression(e, &component));
|
||||||
quote!({ #(#map);* })
|
quote!({ #(#map);* })
|
||||||
}
|
}
|
||||||
Expression::SignalReference(NamedReference { element, name, .. }) => {
|
Expression::SignalReference(NamedReference { element, name, .. }) => access_member(
|
||||||
let access = access_member(
|
|
||||||
&element.upgrade().unwrap(),
|
&element.upgrade().unwrap(),
|
||||||
name.as_str(),
|
name.as_str(),
|
||||||
component,
|
component,
|
||||||
quote!(_self),
|
quote!(_self),
|
||||||
false,
|
false,
|
||||||
);
|
),
|
||||||
quote!(#access.emit(&()))
|
Expression::FunctionCall { function, arguments } => {
|
||||||
}
|
let f = compile_expression(function, &component);
|
||||||
Expression::FunctionCall { function } => {
|
let a = arguments.iter().map(|a| compile_expression(a, &component));
|
||||||
if matches!(function.ty(), Type::Signal{..} | Type::Function{..}) {
|
if matches!(function.ty(), Type::Signal{..}) {
|
||||||
compile_expression(function, &component)
|
quote! { #f.emit(&(#((#a).clone(),)*).into())}
|
||||||
} else {
|
} else {
|
||||||
let error = format!("the function {:?} is not a signal", e);
|
quote! { #f(#(#a.clone()),*)}
|
||||||
quote!(compile_error! {#error})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::SelfAssignment { lhs, rhs, op } => match &**lhs {
|
Expression::SelfAssignment { lhs, rhs, op } => match &**lhs {
|
||||||
|
|
|
@ -253,13 +253,7 @@ impl Expression {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
node.FunctionCallExpression().map(|n| Expression::FunctionCall {
|
node.FunctionCallExpression().map(|n| Self::from_function_call_node(n, ctx))
|
||||||
function: Box::new(
|
|
||||||
n.child_node(SyntaxKind::Expression)
|
|
||||||
.map(|n| Self::from_expression_node(n.into(), ctx))
|
|
||||||
.unwrap_or(Expression::Invalid),
|
|
||||||
),
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.or_else(|| node.SelfAssignment().map(|n| Self::from_self_assignement_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)))
|
.or_else(|| node.BinaryExpression().map(|n| Self::from_binary_expression_node(n, ctx)))
|
||||||
|
@ -470,6 +464,44 @@ impl Expression {
|
||||||
Self::Invalid
|
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(
|
fn from_self_assignement_node(
|
||||||
node: syntax_nodes::SelfAssignment,
|
node: syntax_nodes::SelfAssignment,
|
||||||
ctx: &mut LookupCtx,
|
ctx: &mut LookupCtx,
|
||||||
|
|
|
@ -18,6 +18,17 @@ Xxx := Rectangle {
|
||||||
// ^error{Assignement need to be done on a property}
|
// ^error{Assignement need to be done on a property}
|
||||||
width = x;
|
width = x;
|
||||||
// ^error{Cannot convert string to length}
|
// ^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;
|
x: 12px;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue