From ab665ba7b64480545d03c26671feddf2bc029a9a Mon Sep 17 00:00:00 2001 From: James Blacklock Date: Fri, 15 Oct 2021 01:34:20 -0700 Subject: [PATCH] enable scripts to access the length of arrays --- sixtyfps_compiler/builtin_macros.rs | 1 + sixtyfps_compiler/expression_tree.rs | 7 +++++++ sixtyfps_compiler/generator/cpp.rs | 3 +++ sixtyfps_compiler/generator/rust.rs | 3 +++ sixtyfps_compiler/langtype.rs | 5 +++++ sixtyfps_compiler/lookup.rs | 21 +++++++++++++++++++++ 6 files changed, 40 insertions(+) diff --git a/sixtyfps_compiler/builtin_macros.rs b/sixtyfps_compiler/builtin_macros.rs index e4db53c97..20d1abe36 100644 --- a/sixtyfps_compiler/builtin_macros.rs +++ b/sixtyfps_compiler/builtin_macros.rs @@ -179,6 +179,7 @@ fn to_debug_string( match &ty { Type::Invalid => Expression::Invalid, Type::Void + | Type::InferredGenericType | Type::InferredCallback | Type::InferredProperty | Type::Component(_) diff --git a/sixtyfps_compiler/expression_tree.rs b/sixtyfps_compiler/expression_tree.rs index 8141ba039..a63d576dc 100644 --- a/sixtyfps_compiler/expression_tree.rs +++ b/sixtyfps_compiler/expression_tree.rs @@ -45,6 +45,7 @@ pub enum BuiltinFunction { ColorBrighter, ColorDarker, ImageSize, + ArrayLength, Rgb, ImplicitLayoutInfo(Orientation), RegisterCustomFontByPath, @@ -125,6 +126,10 @@ impl BuiltinFunction { }), args: vec![Type::Image], }, + BuiltinFunction::ArrayLength => Type::Function { + return_type: Box::new(Type::Int32), + args: vec![Type::Array(Box::new(Type::InferredGenericType))], + }, BuiltinFunction::Rgb => Type::Function { return_type: Box::new(Type::Color), args: vec![Type::Int32, Type::Int32, Type::Int32, Type::Float32], @@ -168,6 +173,7 @@ impl BuiltinFunction { BuiltinFunction::ImageSize => true, #[cfg(target_arch = "wasm32")] BuiltinFunction::ImageSize => false, + BuiltinFunction::ArrayLength => true, BuiltinFunction::Rgb => true, BuiltinFunction::ImplicitLayoutInfo(_) => false, BuiltinFunction::RegisterCustomFontByPath @@ -985,6 +991,7 @@ impl Expression { pub fn default_value_for_type(ty: &Type) -> Expression { match ty { Type::Invalid + | Type::InferredGenericType | Type::Component(_) | Type::Builtin(_) | Type::Native(_) diff --git a/sixtyfps_compiler/generator/cpp.rs b/sixtyfps_compiler/generator/cpp.rs index 212b22e0e..5ef8a6a2d 100644 --- a/sixtyfps_compiler/generator/cpp.rs +++ b/sixtyfps_compiler/generator/cpp.rs @@ -1627,6 +1627,9 @@ fn compile_expression( BuiltinFunction::ImageSize => { "[](const sixtyfps::Image &img) { return img.size(); }".into() } + BuiltinFunction::ArrayLength => { + "[](const sixtyfps::Model &model) { return (int) model.row_count(); }".into() + } BuiltinFunction::Rgb => { "[](int r, int g, int b, float a) {{ return sixtyfps::Color::from_argb_uint8(std::clamp(a * 255., 0., 255.), std::clamp(r, 0, 255), std::clamp(g, 0, 255), std::clamp(b, 0, 255)); }}".into() } diff --git a/sixtyfps_compiler/generator/rust.rs b/sixtyfps_compiler/generator/rust.rs index c4089fcd0..87224053c 100644 --- a/sixtyfps_compiler/generator/rust.rs +++ b/sixtyfps_compiler/generator/rust.rs @@ -1238,6 +1238,9 @@ fn compile_expression(expr: &Expression, component: &Rc) -> TokenStre BuiltinFunction::ImageSize => { quote!((|x: Image| -> Size { x.size() })) } + BuiltinFunction::ArrayLength => { + quote!((|x: ModelHandle<_>| -> i32 { x.row_count() as i32 })) + } BuiltinFunction::Rgb => { quote!((|r: i32, g: i32, b: i32, a: f32| { diff --git a/sixtyfps_compiler/langtype.rs b/sixtyfps_compiler/langtype.rs index 7d58d604a..18797b347 100644 --- a/sixtyfps_compiler/langtype.rs +++ b/sixtyfps_compiler/langtype.rs @@ -76,11 +76,14 @@ pub enum Type { /// This is a `SharedArray` LayoutCache, + + InferredGenericType, } impl core::cmp::PartialEq for Type { fn eq(&self, other: &Self) -> bool { match self { + Type::InferredGenericType => true, Type::Invalid => matches!(other, Type::Invalid), Type::Void => matches!(other, Type::Void), Type::InferredProperty => matches!(other, Type::InferredProperty), @@ -124,6 +127,7 @@ impl core::cmp::PartialEq for Type { impl Display for Type { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { + Type::InferredGenericType => write!(f, "<_>"), Type::Invalid => write!(f, ""), Type::Void => write!(f, "void"), Type::InferredProperty => write!(f, "?"), @@ -469,6 +473,7 @@ impl Type { // Unit::Percent is special that it does not combine with other units like Type::Percent => None, Type::Angle => Some(Unit::Deg), + Type::InferredGenericType => None, Type::Invalid => None, Type::Void => None, Type::InferredProperty | Type::InferredCallback => None, diff --git a/sixtyfps_compiler/lookup.rs b/sixtyfps_compiler/lookup.rs index 3fba80c01..a860716c3 100644 --- a/sixtyfps_compiler/lookup.rs +++ b/sixtyfps_compiler/lookup.rs @@ -521,6 +521,7 @@ impl LookupObject for Expression { Type::String => StringExpression(self).for_each_entry(ctx, f), Type::Color => ColorExpression(self).for_each_entry(ctx, f), Type::Image => ImageExpression(self).for_each_entry(ctx, f), + Type::Array(_) => ArrayExpression(self).for_each_entry(ctx, f), _ => None, }, } @@ -547,6 +548,7 @@ impl LookupObject for Expression { Type::String => StringExpression(self).lookup(ctx, name), Type::Color => ColorExpression(self).lookup(ctx, name), Type::Image => ImageExpression(self).lookup(ctx, name), + Type::Array(_) => ArrayExpression(self).lookup(ctx, name), _ => None, }, } @@ -614,3 +616,22 @@ impl<'a> LookupObject for ImageExpression<'a> { .or_else(|| f("height", field_access("height"))) } } + +struct ArrayExpression<'a>(&'a Expression); +impl<'a> LookupObject for ArrayExpression<'a> { + fn for_each_entry( + &self, + ctx: &LookupCtx, + f: &mut impl FnMut(&str, Expression) -> Option, + ) -> Option { + let member_function = |f: BuiltinFunction| Expression::FunctionCall { + function: Box::new(Expression::BuiltinFunctionReference( + f, + ctx.current_token.as_ref().map(|t| t.to_source_location()), + )), + source_location: ctx.current_token.as_ref().map(|t| t.to_source_location()), + arguments: vec![self.0.clone()], + }; + None.or_else(|| f("length", member_function(BuiltinFunction::ArrayLength))) + } +}