mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-30 22:01:13 +00:00
Represent the window scale factor conversions in the IR
That means less code in the generators and easier to extend in the future with more built-in functions.
This commit is contained in:
parent
1d0eacc87f
commit
41671e3efb
6 changed files with 87 additions and 26 deletions
|
@ -117,6 +117,7 @@ fn to_eval_value<'cx>(
|
||||||
| Type::Component(_)
|
| Type::Component(_)
|
||||||
| Type::Builtin(_)
|
| Type::Builtin(_)
|
||||||
| Type::Native(_)
|
| Type::Native(_)
|
||||||
|
| Type::Function { .. }
|
||||||
| Type::Model
|
| Type::Model
|
||||||
| Type::Signal
|
| Type::Signal
|
||||||
| Type::Easing
|
| Type::Easing
|
||||||
|
|
|
@ -30,6 +30,22 @@ impl Hash for NamedReference {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
/// A function built into the run-time
|
||||||
|
pub enum BuiltinFunction {
|
||||||
|
GetWindowScaleFactor,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BuiltinFunction {
|
||||||
|
fn ty(&self) -> Type {
|
||||||
|
match self {
|
||||||
|
BuiltinFunction::GetWindowScaleFactor => {
|
||||||
|
Type::Function { return_type: Box::new(Type::Float32), args: vec![] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub enum OperatorClass {
|
pub enum OperatorClass {
|
||||||
ComparisonOp,
|
ComparisonOp,
|
||||||
|
@ -147,6 +163,9 @@ pub enum Expression {
|
||||||
/// Reference to the signal <name> in the <element>
|
/// Reference to the signal <name> in the <element>
|
||||||
PropertyReference(NamedReference),
|
PropertyReference(NamedReference),
|
||||||
|
|
||||||
|
/// Reference to a function built into the run-time, implemented natively
|
||||||
|
BuiltinFunctionReference(BuiltinFunction),
|
||||||
|
|
||||||
/// Reference to the index variable of a repeater
|
/// Reference to the index variable of a repeater
|
||||||
///
|
///
|
||||||
/// Example: `idx` in `for xxx[idx] in ...`. The element is the reference to the
|
/// Example: `idx` in `for xxx[idx] in ...`. The element is the reference to the
|
||||||
|
@ -263,6 +282,7 @@ impl Expression {
|
||||||
Expression::PropertyReference(NamedReference { element, name }) => {
|
Expression::PropertyReference(NamedReference { element, name }) => {
|
||||||
element.upgrade().unwrap().borrow().lookup_property(name)
|
element.upgrade().unwrap().borrow().lookup_property(name)
|
||||||
}
|
}
|
||||||
|
Expression::BuiltinFunctionReference(funcref) => funcref.ty(),
|
||||||
Expression::RepeaterIndexReference { .. } => Type::Int32,
|
Expression::RepeaterIndexReference { .. } => Type::Int32,
|
||||||
Expression::RepeaterModelReference { element } => {
|
Expression::RepeaterModelReference { element } => {
|
||||||
if let Expression::Cast { from, .. } = element
|
if let Expression::Cast { from, .. } = element
|
||||||
|
@ -345,6 +365,7 @@ impl Expression {
|
||||||
Expression::BoolLiteral(_) => {}
|
Expression::BoolLiteral(_) => {}
|
||||||
Expression::SignalReference { .. } => {}
|
Expression::SignalReference { .. } => {}
|
||||||
Expression::PropertyReference { .. } => {}
|
Expression::PropertyReference { .. } => {}
|
||||||
|
Expression::BuiltinFunctionReference { .. } => {}
|
||||||
Expression::ObjectAccess { base, .. } => visitor(&**base),
|
Expression::ObjectAccess { base, .. } => visitor(&**base),
|
||||||
Expression::RepeaterIndexReference { .. } => {}
|
Expression::RepeaterIndexReference { .. } => {}
|
||||||
Expression::RepeaterModelReference { .. } => {}
|
Expression::RepeaterModelReference { .. } => {}
|
||||||
|
@ -402,6 +423,7 @@ impl Expression {
|
||||||
Expression::BoolLiteral(_) => {}
|
Expression::BoolLiteral(_) => {}
|
||||||
Expression::SignalReference { .. } => {}
|
Expression::SignalReference { .. } => {}
|
||||||
Expression::PropertyReference { .. } => {}
|
Expression::PropertyReference { .. } => {}
|
||||||
|
Expression::BuiltinFunctionReference { .. } => {}
|
||||||
Expression::ObjectAccess { base, .. } => visitor(&mut **base),
|
Expression::ObjectAccess { base, .. } => visitor(&mut **base),
|
||||||
Expression::RepeaterIndexReference { .. } => {}
|
Expression::RepeaterIndexReference { .. } => {}
|
||||||
Expression::RepeaterModelReference { .. } => {}
|
Expression::RepeaterModelReference { .. } => {}
|
||||||
|
@ -459,6 +481,7 @@ impl Expression {
|
||||||
Expression::BoolLiteral(_) => true,
|
Expression::BoolLiteral(_) => true,
|
||||||
Expression::SignalReference { .. } => false,
|
Expression::SignalReference { .. } => false,
|
||||||
Expression::PropertyReference { .. } => false,
|
Expression::PropertyReference { .. } => false,
|
||||||
|
Expression::BuiltinFunctionReference { .. } => false,
|
||||||
Expression::RepeaterIndexReference { .. } => false,
|
Expression::RepeaterIndexReference { .. } => false,
|
||||||
Expression::RepeaterModelReference { .. } => false,
|
Expression::RepeaterModelReference { .. } => false,
|
||||||
Expression::ObjectAccess { base, .. } => base.is_constant(),
|
Expression::ObjectAccess { base, .. } => base.is_constant(),
|
||||||
|
@ -500,7 +523,28 @@ impl Expression {
|
||||||
if ty == target_type {
|
if ty == target_type {
|
||||||
self
|
self
|
||||||
} else if ty.can_convert(&target_type) {
|
} else if ty.can_convert(&target_type) {
|
||||||
Expression::Cast { from: Box::new(self), to: target_type }
|
let from = match (ty, &target_type) {
|
||||||
|
(Type::Length, Type::LogicalLength) => Expression::BinaryExpression {
|
||||||
|
lhs: Box::new(self),
|
||||||
|
rhs: Box::new(Expression::FunctionCall {
|
||||||
|
function: Box::new(Expression::BuiltinFunctionReference(
|
||||||
|
BuiltinFunction::GetWindowScaleFactor,
|
||||||
|
)),
|
||||||
|
}),
|
||||||
|
op: '/',
|
||||||
|
},
|
||||||
|
(Type::LogicalLength, Type::Length) => Expression::BinaryExpression {
|
||||||
|
lhs: Box::new(self),
|
||||||
|
rhs: Box::new(Expression::FunctionCall {
|
||||||
|
function: Box::new(Expression::BuiltinFunctionReference(
|
||||||
|
BuiltinFunction::GetWindowScaleFactor,
|
||||||
|
)),
|
||||||
|
}),
|
||||||
|
op: '*',
|
||||||
|
},
|
||||||
|
_ => self,
|
||||||
|
};
|
||||||
|
Expression::Cast { from: Box::new(from), to: target_type }
|
||||||
} else if ty == Type::Invalid || target_type == Type::Invalid {
|
} else if ty == Type::Invalid || target_type == Type::Invalid {
|
||||||
self
|
self
|
||||||
} else {
|
} else {
|
||||||
|
@ -517,6 +561,7 @@ impl Expression {
|
||||||
| Type::Builtin(_)
|
| Type::Builtin(_)
|
||||||
| Type::Native(_)
|
| Type::Native(_)
|
||||||
| Type::Signal
|
| Type::Signal
|
||||||
|
| Type::Function { .. }
|
||||||
| Type::Void => Expression::Invalid,
|
| Type::Void => Expression::Invalid,
|
||||||
Type::Float32 => Expression::NumberLiteral(0., Unit::None),
|
Type::Float32 => Expression::NumberLiteral(0., Unit::None),
|
||||||
Type::Int32 => Expression::NumberLiteral(0., Unit::None),
|
Type::Int32 => Expression::NumberLiteral(0., Unit::None),
|
||||||
|
|
|
@ -155,7 +155,7 @@ mod cpp_ast {
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::diagnostics::{BuildDiagnostics, CompilerDiagnostic, Spanned};
|
use crate::diagnostics::{BuildDiagnostics, CompilerDiagnostic, Spanned};
|
||||||
use crate::expression_tree::{EasingCurve, Expression, ExpressionSpanned};
|
use crate::expression_tree::{BuiltinFunction, EasingCurve, Expression, ExpressionSpanned};
|
||||||
use crate::layout::{GridLayout, Layout, LayoutItem, PathLayout};
|
use crate::layout::{GridLayout, Layout, LayoutItem, PathLayout};
|
||||||
use crate::object_tree::{Component, Element, ElementRc, RepeatedElementInfo};
|
use crate::object_tree::{Component, Element, ElementRc, RepeatedElementInfo};
|
||||||
use crate::typeregister::Type;
|
use crate::typeregister::Type;
|
||||||
|
@ -843,6 +843,9 @@ 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#"{}.emit()"#, access)
|
format!(r#"{}.emit()"#, access)
|
||||||
}
|
}
|
||||||
|
Expression::BuiltinFunctionReference(funcref) => match funcref {
|
||||||
|
BuiltinFunction::GetWindowScaleFactor => window_scale_factor_expression(component),
|
||||||
|
},
|
||||||
Expression::RepeaterIndexReference { element } => {
|
Expression::RepeaterIndexReference { element } => {
|
||||||
if element.upgrade().unwrap().borrow().base_type == Type::Component(component.clone()) {
|
if element.upgrade().unwrap().borrow().base_type == Type::Component(component.clone()) {
|
||||||
"self->index.get()".to_owned()
|
"self->index.get()".to_owned()
|
||||||
|
@ -882,12 +885,6 @@ fn compile_expression(e: &crate::expression_tree::Expression, component: &Rc<Com
|
||||||
}
|
}
|
||||||
(Type::Array(_), Type::Model) => f,
|
(Type::Array(_), Type::Model) => f,
|
||||||
(Type::Float32, Type::Color) => format!("sixtyfps::Color({})", f),
|
(Type::Float32, Type::Color) => format!("sixtyfps::Color({})", f),
|
||||||
(Type::LogicalLength, Type::Length) => {
|
|
||||||
format!("({} * {})", f, window_scale_factor_expression(component))
|
|
||||||
}
|
|
||||||
(Type::Length, Type::LogicalLength) => {
|
|
||||||
format!("({} / {})", f, window_scale_factor_expression(component))
|
|
||||||
}
|
|
||||||
_ => f,
|
_ => f,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -898,7 +895,7 @@ fn compile_expression(e: &crate::expression_tree::Expression, component: &Rc<Com
|
||||||
format!("[&]{{ {} }}()", x.join(";"))
|
format!("[&]{{ {} }}()", x.join(";"))
|
||||||
}
|
}
|
||||||
Expression::FunctionCall { function } => {
|
Expression::FunctionCall { function } => {
|
||||||
if matches!(function.ty(), Type::Signal) {
|
if matches!(function.ty(), Type::Signal | Type::Function{..}) {
|
||||||
compile_expression(&*function, component)
|
compile_expression(&*function, component)
|
||||||
} else {
|
} else {
|
||||||
format!("\n#error the function `{:?}` is not a signal\n", function)
|
format!("\n#error the function `{:?}` is not a signal\n", function)
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::diagnostics::{BuildDiagnostics, CompilerDiagnostic, Spanned};
|
use crate::diagnostics::{BuildDiagnostics, CompilerDiagnostic, Spanned};
|
||||||
use crate::expression_tree::{EasingCurve, Expression, NamedReference, OperatorClass, Path};
|
use crate::expression_tree::{
|
||||||
|
BuiltinFunction, EasingCurve, Expression, NamedReference, OperatorClass, Path,
|
||||||
|
};
|
||||||
use crate::object_tree::{Component, ElementRc};
|
use crate::object_tree::{Component, ElementRc};
|
||||||
use crate::{
|
use crate::{
|
||||||
layout::{GridLayout, Layout, LayoutItem, PathLayout},
|
layout::{GridLayout, Layout, LayoutItem, PathLayout},
|
||||||
|
@ -607,14 +609,6 @@ fn compile_expression(e: &Expression, component: &Rc<Component>) -> TokenStream
|
||||||
(Type::Float32, Type::Color) => {
|
(Type::Float32, Type::Color) => {
|
||||||
quote!(sixtyfps::re_exports::Color::from(#f as u32))
|
quote!(sixtyfps::re_exports::Color::from(#f as u32))
|
||||||
}
|
}
|
||||||
(Type::LogicalLength, Type::Length) => {
|
|
||||||
let window_scale_factor_expression = window_scale_factor_expression(component);
|
|
||||||
quote!((#f as f64) * #window_scale_factor_expression as f64)
|
|
||||||
}
|
|
||||||
(Type::Length, Type::LogicalLength) => {
|
|
||||||
let window_scale_factor_expression = window_scale_factor_expression(component);
|
|
||||||
quote!((#f as f64) / #window_scale_factor_expression as f64)
|
|
||||||
}
|
|
||||||
_ => f,
|
_ => f,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -623,6 +617,9 @@ fn compile_expression(e: &Expression, component: &Rc<Component>) -> TokenStream
|
||||||
access_member(&element.upgrade().unwrap(), name.as_str(), component, quote!(_self));
|
access_member(&element.upgrade().unwrap(), name.as_str(), component, quote!(_self));
|
||||||
quote!(#access.get())
|
quote!(#access.get())
|
||||||
}
|
}
|
||||||
|
Expression::BuiltinFunctionReference(funcref) => match funcref {
|
||||||
|
BuiltinFunction::GetWindowScaleFactor => window_scale_factor_expression(component),
|
||||||
|
},
|
||||||
Expression::RepeaterIndexReference { element } => {
|
Expression::RepeaterIndexReference { element } => {
|
||||||
if element.upgrade().unwrap().borrow().base_type == Type::Component(component.clone()) {
|
if element.upgrade().unwrap().borrow().base_type == Type::Component(component.clone()) {
|
||||||
let component_id = component_id(&component);
|
let component_id = component_id(&component);
|
||||||
|
@ -661,7 +658,7 @@ fn compile_expression(e: &Expression, component: &Rc<Component>) -> TokenStream
|
||||||
quote!(#access.emit(()))
|
quote!(#access.emit(()))
|
||||||
}
|
}
|
||||||
Expression::FunctionCall { function } => {
|
Expression::FunctionCall { function } => {
|
||||||
if matches!(function.ty(), Type::Signal) {
|
if matches!(function.ty(), Type::Signal | Type::Function{..}) {
|
||||||
compile_expression(function, &component)
|
compile_expression(function, &component)
|
||||||
} else {
|
} else {
|
||||||
let error = format!("the function {:?} is not a signal", e);
|
let error = format!("the function {:?} is not a signal", e);
|
||||||
|
|
|
@ -12,6 +12,10 @@ pub enum Type {
|
||||||
Native(Rc<NativeClass>),
|
Native(Rc<NativeClass>),
|
||||||
|
|
||||||
Signal,
|
Signal,
|
||||||
|
Function {
|
||||||
|
return_type: Box<Type>,
|
||||||
|
args: Vec<Type>,
|
||||||
|
},
|
||||||
|
|
||||||
// Other property types:
|
// Other property types:
|
||||||
Float32,
|
Float32,
|
||||||
|
@ -40,6 +44,10 @@ impl core::cmp::PartialEq for Type {
|
||||||
(Type::Builtin(a), Type::Builtin(b)) => Rc::ptr_eq(a, b),
|
(Type::Builtin(a), Type::Builtin(b)) => Rc::ptr_eq(a, b),
|
||||||
(Type::Native(a), Type::Native(b)) => Rc::ptr_eq(a, b),
|
(Type::Native(a), Type::Native(b)) => Rc::ptr_eq(a, b),
|
||||||
(Type::Signal, Type::Signal) => true,
|
(Type::Signal, Type::Signal) => true,
|
||||||
|
(
|
||||||
|
Type::Function { return_type: lhs_rt, args: lhs_args },
|
||||||
|
Type::Function { return_type: rhs_rt, args: rhs_args },
|
||||||
|
) => lhs_rt == rhs_rt && lhs_args == rhs_args,
|
||||||
(Type::Float32, Type::Float32) => true,
|
(Type::Float32, Type::Float32) => true,
|
||||||
(Type::Int32, Type::Int32) => true,
|
(Type::Int32, Type::Int32) => true,
|
||||||
(Type::String, Type::String) => true,
|
(Type::String, Type::String) => true,
|
||||||
|
@ -68,6 +76,16 @@ impl Display for Type {
|
||||||
Type::Builtin(b) => b.native_class.class_name.fmt(f),
|
Type::Builtin(b) => b.native_class.class_name.fmt(f),
|
||||||
Type::Native(b) => b.class_name.fmt(f),
|
Type::Native(b) => b.class_name.fmt(f),
|
||||||
Type::Signal => write!(f, "signal"),
|
Type::Signal => write!(f, "signal"),
|
||||||
|
Type::Function { return_type, args } => {
|
||||||
|
write!(f, "function(")?;
|
||||||
|
for (i, arg) in args.iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
write!(f, ",")?;
|
||||||
|
}
|
||||||
|
write!(f, "{}", arg)?;
|
||||||
|
}
|
||||||
|
write!(f, ") -> {}", return_type)
|
||||||
|
}
|
||||||
Type::Float32 => write!(f, "float"),
|
Type::Float32 => write!(f, "float"),
|
||||||
Type::Int32 => write!(f, "int"),
|
Type::Int32 => write!(f, "int"),
|
||||||
Type::String => write!(f, "string"),
|
Type::String => write!(f, "string"),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use core::convert::{TryFrom, TryInto};
|
use core::convert::{TryFrom, TryInto};
|
||||||
use core::pin::Pin;
|
use core::pin::Pin;
|
||||||
use sixtyfps_compilerlib::expression_tree::{
|
use sixtyfps_compilerlib::expression_tree::{
|
||||||
EasingCurve, Expression, ExpressionSpanned, NamedReference, Path as ExprPath,
|
BuiltinFunction, EasingCurve, Expression, ExpressionSpanned, NamedReference, Path as ExprPath,
|
||||||
PathElement as ExprPathElement,
|
PathElement as ExprPathElement,
|
||||||
};
|
};
|
||||||
use sixtyfps_compilerlib::{object_tree::ElementRc, typeregister::Type};
|
use sixtyfps_compilerlib::{object_tree::ElementRc, typeregister::Type};
|
||||||
|
@ -138,6 +138,9 @@ pub fn eval_expression(
|
||||||
Expression::NumberLiteral(n, unit) => Value::Number(unit.normalize(*n)),
|
Expression::NumberLiteral(n, unit) => Value::Number(unit.normalize(*n)),
|
||||||
Expression::BoolLiteral(b) => Value::Bool(*b),
|
Expression::BoolLiteral(b) => Value::Bool(*b),
|
||||||
Expression::SignalReference { .. } => panic!("signal in expression"),
|
Expression::SignalReference { .. } => panic!("signal in expression"),
|
||||||
|
Expression::BuiltinFunctionReference(_) => panic!(
|
||||||
|
"naked builtin function reference not allowed, should be handled by function call"
|
||||||
|
),
|
||||||
Expression::PropertyReference(NamedReference { element, name }) => {
|
Expression::PropertyReference(NamedReference { element, name }) => {
|
||||||
let element = element.upgrade().unwrap();
|
let element = element.upgrade().unwrap();
|
||||||
let (component_mem, component_type, _) =
|
let (component_mem, component_type, _) =
|
||||||
|
@ -197,12 +200,6 @@ pub fn eval_expression(
|
||||||
Value::String(SharedString::from(format!("{}", n).as_str()))
|
Value::String(SharedString::from(format!("{}", n).as_str()))
|
||||||
}
|
}
|
||||||
(Value::Number(n), Type::Color) => Value::Color(Color::from(n as u32)),
|
(Value::Number(n), Type::Color) => Value::Color(Color::from(n as u32)),
|
||||||
(Value::Number(n), Type::Length) => {
|
|
||||||
Value::Number(n * window_scale_factor(component_type, component_ref))
|
|
||||||
}
|
|
||||||
(Value::Number(n), Type::LogicalLength) => {
|
|
||||||
Value::Number(n / window_scale_factor(component_type, component_ref))
|
|
||||||
}
|
|
||||||
(v, _) => v,
|
(v, _) => v,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,6 +235,12 @@ pub fn eval_expression(
|
||||||
};
|
};
|
||||||
signal.emit(());
|
signal.emit(());
|
||||||
Value::Void
|
Value::Void
|
||||||
|
} else if let Expression::BuiltinFunctionReference(funcref) = &**function {
|
||||||
|
match funcref {
|
||||||
|
BuiltinFunction::GetWindowScaleFactor => {
|
||||||
|
Value::Number(window_scale_factor(component_type, component_ref))
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!("call of something not a signal")
|
panic!("call of something not a signal")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue