Emit signal handler bindings and expressions for emitting signals in the Rust frontend

This commit is contained in:
Simon Hausmann 2020-05-28 15:12:50 +02:00
parent a3892ea102
commit 97dc677854

View file

@ -196,26 +196,30 @@ pub fn sixtyfps(stream: TokenStream) -> TokenStream {
quote!(#field_name.) quote!(#field_name.)
}; };
let rust_property = quote!(#rust_property_accessor_prefix#rust_property_ident); let rust_property = quote!(#rust_property_accessor_prefix#rust_property_ident);
let tokens_for_expression = compile_expression(binding_expression);
let v = compile_expression(binding_expression); if matches!(item.lookup_property(k.as_str()), Type::Signal) {
if v.is_none() { init.push(quote!(
// FIXME: this is because signals are not yet implemented self_.#rust_property.set_handler(|context, ()| {
continue; let _self = context.component.downcast::<#component_id>().unwrap();
} #tokens_for_expression;
});
));
} else {
if binding_expression.is_constant() { if binding_expression.is_constant() {
init.push(quote!( init.push(quote!(
self_.#rust_property.set(#v); self_.#rust_property.set(#tokens_for_expression);
)); ));
} else { } else {
init.push(quote!( init.push(quote!(
self_.#rust_property.set_binding(|context| { self_.#rust_property.set_binding(|context| {
let _self = context.component.downcast::<#component_id>().unwrap(); let _self = context.component.downcast::<#component_id>().unwrap();
#v #tokens_for_expression
}); });
)); ));
} }
} }
}
item_names.push(field_name); item_names.push(field_name);
item_types.push(quote::format_ident!("{}", item.base_type.as_builtin().class_name)); item_types.push(quote::format_ident!("{}", item.base_type.as_builtin().class_name));
}); });
@ -269,12 +273,12 @@ pub fn sixtyfps(stream: TokenStream) -> TokenStream {
result.into() result.into()
} }
fn compile_expression(e: &Expression) -> Option<proc_macro2::TokenStream> { fn compile_expression(e: &Expression) -> proc_macro2::TokenStream {
Some(match e { match e {
Expression::StringLiteral(s) => quote!(sixtyfps::re_exports::SharedString::from(#s)), Expression::StringLiteral(s) => quote!(sixtyfps::re_exports::SharedString::from(#s)),
Expression::NumberLiteral(n) => quote!(#n as _), Expression::NumberLiteral(n) => quote!(#n as _),
Expression::Cast { from, to } => { Expression::Cast { from, to } => {
let f = compile_expression(&*from)?; let f = compile_expression(&*from);
match (from.ty(), to) { match (from.ty(), to) {
(Type::Float32, Type::String) | (Type::Int32, Type::String) => { (Type::Float32, Type::String) | (Type::Int32, Type::String) => {
quote!(sixtyfps::re_exports::SharedString::from(format("{}", #f).to_str())) quote!(sixtyfps::re_exports::SharedString::from(format("{}", #f).to_str()))
@ -293,19 +297,32 @@ fn compile_expression(e: &Expression) -> Option<proc_macro2::TokenStream> {
} }
} }
Expression::CodeBlock(sub) => { Expression::CodeBlock(sub) => {
if sub.iter().map(|e| compile_expression(e)).any(|e| e.is_none()) {
// fixme: Remove!
return None;
}
let map = sub.iter().map(|e| compile_expression(e)); let map = sub.iter().map(|e| compile_expression(e));
quote!({ #(#map);* }) quote!({ #(#map);* })
} }
// FIXME: signals! // FIXME: signals!
Expression::SignalReference { .. } => return None, Expression::SignalReference { element, name, .. } => {
Expression::FunctionCall { .. } => return None, let name_ident = quote::format_ident!("{}", name);
let e = element.upgrade().unwrap();
if !e.borrow().property_declarations.contains_key(name) {
let elem_ident = quote::format_ident!("{}", e.borrow().id);
quote!(_self.#elem_ident.#name_ident)
} else {
quote!(_self.#name_ident)
}
}
Expression::FunctionCall { function } => {
if matches!(function.ty(), Type::Signal) {
let base = compile_expression(function);
quote!(#base.emit(&context, ()))
} else {
let error = format!("the function {:?} is not a signal", e);
quote!(compile_error! {#error})
}
}
_ => { _ => {
let error = format!("unsupported expression {:?}", e); let error = format!("unsupported expression {:?}", e);
quote!(compile_error! {#error}) quote!(compile_error! {#error})
} }
}) }
} }