mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-04 18:58:36 +00:00
Slint: make the abs work with unit types
This commit is contained in:
parent
8dcd9713ff
commit
0929e3dfc1
6 changed files with 96 additions and 3 deletions
|
@ -90,9 +90,9 @@ against the constants below.
|
|||
|
||||
These functions are available both in the global scope and in the `Math` namespace.
|
||||
|
||||
### `abs(float) -> float`
|
||||
### `abs(T) -> T`
|
||||
|
||||
Return the absolute value.
|
||||
Return the absolute value, where T is a numeric type.
|
||||
|
||||
### `acos(float) -> angle`, `asin(float) -> angle`, `atan(float) -> angle`, `cos(angle) -> float`, `sin(angle) -> float`, `tan(angle) -> float`
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ pub fn lower_macro(
|
|||
BuiltinMacroFunction::Max => min_max_macro(n, MinMaxOp::Max, sub_expr.collect(), diag),
|
||||
BuiltinMacroFunction::Clamp => clamp_macro(n, sub_expr.collect(), diag),
|
||||
BuiltinMacroFunction::Mod => mod_macro(n, sub_expr.collect(), diag),
|
||||
BuiltinMacroFunction::Abs => abs_macro(n, sub_expr.collect(), diag),
|
||||
BuiltinMacroFunction::Debug => debug_macro(n, sub_expr.collect(), diag),
|
||||
BuiltinMacroFunction::CubicBezier => {
|
||||
let mut has_error = None;
|
||||
|
@ -183,6 +184,47 @@ fn mod_macro(
|
|||
}
|
||||
}
|
||||
|
||||
fn abs_macro(
|
||||
node: Option<NodeOrToken>,
|
||||
args: Vec<(Expression, Option<NodeOrToken>)>,
|
||||
diag: &mut BuildDiagnostics,
|
||||
) -> Expression {
|
||||
if args.len() != 1 {
|
||||
diag.push_error("Needs 1 argument".into(), &node);
|
||||
return Expression::Invalid;
|
||||
}
|
||||
let ty = args[0].0.ty();
|
||||
let ty = if ty.default_unit().is_some() || matches!(ty, Type::UnitProduct(_)) {
|
||||
ty
|
||||
} else {
|
||||
Type::Float32
|
||||
};
|
||||
|
||||
let source_location = node.map(|n| n.to_source_location());
|
||||
let function = Box::new(Expression::BuiltinFunctionReference(
|
||||
BuiltinFunction::Abs,
|
||||
source_location.clone(),
|
||||
));
|
||||
if matches!(ty, Type::Float32) {
|
||||
let arguments =
|
||||
args.into_iter().map(|(e, n)| e.maybe_convert_to(ty.clone(), &n, diag)).collect();
|
||||
Expression::FunctionCall { function, arguments, source_location }
|
||||
} else {
|
||||
Expression::Cast {
|
||||
from: Expression::FunctionCall {
|
||||
function,
|
||||
arguments: args
|
||||
.into_iter()
|
||||
.map(|(a, _)| Expression::Cast { from: a.into(), to: Type::Float32 })
|
||||
.collect(),
|
||||
source_location,
|
||||
}
|
||||
.into(),
|
||||
to: ty,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn rgb_macro(
|
||||
node: Option<NodeOrToken>,
|
||||
args: Vec<(Expression, Option<NodeOrToken>)>,
|
||||
|
|
|
@ -85,6 +85,8 @@ pub enum BuiltinMacroFunction {
|
|||
Clamp,
|
||||
/// Add the right conversion operations so that the return type is the same as the argument type
|
||||
Mod,
|
||||
/// Add the right conversion operations so that the return type is the same as the argument type
|
||||
Abs,
|
||||
CubicBezier,
|
||||
/// The argument can be r,g,b,a or r,g,b and they can be percentages or integer.
|
||||
/// transform the argument so it is always rgb(r, g, b, a) with r, g, b between 0 and 255.
|
||||
|
|
|
@ -786,7 +786,7 @@ impl LookupObject for MathFunctions {
|
|||
.or_else(|| f("ceil", BuiltinFunctionReference(BuiltinFunction::Ceil, sl())))
|
||||
.or_else(|| f("floor", BuiltinFunctionReference(BuiltinFunction::Floor, sl())))
|
||||
.or_else(|| f("clamp", BuiltinMacroReference(BuiltinMacroFunction::Clamp, t.clone())))
|
||||
.or_else(|| f("abs", BuiltinFunctionReference(BuiltinFunction::Abs, sl())))
|
||||
.or_else(|| f("abs", BuiltinMacroReference(BuiltinMacroFunction::Abs, t.clone())))
|
||||
.or_else(|| f("sqrt", BuiltinFunctionReference(BuiltinFunction::Sqrt, sl())))
|
||||
.or_else(|| f("max", BuiltinMacroReference(BuiltinMacroFunction::Max, t.clone())))
|
||||
.or_else(|| f("min", BuiltinMacroReference(BuiltinMacroFunction::Min, t.clone())))
|
||||
|
|
44
internal/compiler/tests/syntax/expressions/math-macro.slint
Normal file
44
internal/compiler/tests/syntax/expressions/math-macro.slint
Normal file
|
@ -0,0 +1,44 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.2 OR LicenseRef-Slint-commercial
|
||||
|
||||
|
||||
export component Foo {
|
||||
property <float> m1: mod(4);
|
||||
// ^error{Needs 2 arguments}
|
||||
|
||||
property <float> m2: mod(4, 5, 5);
|
||||
// ^error{Needs 2 arguments}
|
||||
|
||||
property <float> m3: mod("455", "465");
|
||||
// ^error{Cannot convert string to float}
|
||||
// ^^error{Cannot convert string to float}
|
||||
|
||||
property <float> m4: mod(455, "465");
|
||||
// ^error{Cannot convert string to float}
|
||||
|
||||
property <length> m5: mod(45px, 4);
|
||||
// ^error{Cannot convert float to length}
|
||||
|
||||
property <length> m6: mod(45px, 4ms);
|
||||
// ^error{Cannot convert duration to length}
|
||||
|
||||
property <duration> m7: mod(5, 4ms);
|
||||
// ^error{Cannot convert float to duration}
|
||||
|
||||
|
||||
property <float> a1: abs();
|
||||
// ^error{Needs 1 argument}
|
||||
|
||||
property <float> a2: abs(4, 5, 5);
|
||||
// ^error{Needs 1 argument}
|
||||
|
||||
property <float> a3: abs(1, 2);
|
||||
// ^error{Needs 1 argument}
|
||||
|
||||
property <float> a4: abs("465");
|
||||
// ^error{Cannot convert string to float}
|
||||
|
||||
property <string> a5: abs(45px);
|
||||
// ^error{Cannot convert length to string}
|
||||
|
||||
}
|
|
@ -6,6 +6,8 @@
|
|||
property<float> t2: abs(-42.3);
|
||||
property<int> t3: abs(42.3);
|
||||
property<int> t4: abs(-42.3);
|
||||
|
||||
out property <bool> test: abs(-45.5px) == 45.5px && abs(78.5deg) == abs(78.5deg) && abs(-1.2s) == 1200ms;
|
||||
}
|
||||
/*
|
||||
```cpp
|
||||
|
@ -15,6 +17,7 @@ assert(std::abs(instance.get_t1() - 42.3) < 0.0001);
|
|||
assert(std::abs(instance.get_t2() - 42.3) < 0.0001);
|
||||
assert_eq(instance.get_t3(), 42);
|
||||
assert_eq(instance.get_t4(), 42);
|
||||
assert(instance.get_test());
|
||||
```
|
||||
|
||||
```rust
|
||||
|
@ -23,6 +26,7 @@ assert_eq!(instance.get_t1(), 42.3);
|
|||
assert_eq!(instance.get_t2(), 42.3);
|
||||
assert_eq!(instance.get_t3(), 42);
|
||||
assert_eq!(instance.get_t4(), 42);
|
||||
assert!(instance.get_test());
|
||||
```
|
||||
|
||||
```js
|
||||
|
@ -31,5 +35,6 @@ assert(Math.abs(instance.t1 - 42.3) < 0.0001);
|
|||
assert(Math.abs(instance.t2 - 42.3) < 0.0001);
|
||||
assert.equal(instance.t3, 42);
|
||||
assert.equal(instance.t4, 42);
|
||||
assert(instance.test);
|
||||
```
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue