Start implementing some code that passes argument to functions and signals

This commit is contained in:
Olivier Goffart 2020-09-08 14:37:44 +02:00
parent a192ffe283
commit a6504ee61b
6 changed files with 100 additions and 53 deletions

View file

@ -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); }

View file

@ -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: '*',
}, },

View file

@ -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 }) => {

View file

@ -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, ),
); Expression::FunctionCall { function, arguments } => {
quote!(#access.emit(&())) let f = compile_expression(function, &component);
} let a = arguments.iter().map(|a| compile_expression(a, &component));
Expression::FunctionCall { function } => { if matches!(function.ty(), Type::Signal{..}) {
if matches!(function.ty(), Type::Signal{..} | Type::Function{..}) { quote! { #f.emit(&(#((#a).clone(),)*).into())}
compile_expression(function, &component)
} 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 {

View file

@ -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,

View file

@ -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;