From fe8373739d8b1c38f9627860d3c629062df07d41 Mon Sep 17 00:00:00 2001 From: David Wendt Date: Fri, 2 Oct 2020 20:22:44 -0400 Subject: [PATCH] avm2: Add the ability to fork a `Class` to one that holds it's type arguments. --- core/src/avm2/class.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/core/src/avm2/class.rs b/core/src/avm2/class.rs index 6f96cb307..3ed80c85f 100644 --- a/core/src/avm2/class.rs +++ b/core/src/avm2/class.rs @@ -29,6 +29,9 @@ bitflags! { /// Class is an interface. const INTERFACE = 1 << 2; + + /// Class accepts type parameters. + const GENERIC = 1 << 3; } } @@ -71,6 +74,9 @@ pub struct Class<'gc> { /// The name of the class. name: QName<'gc>, + /// The type parameters for this class. + params: Vec>>, + /// The name of this class's superclass. super_class: Option>, @@ -214,6 +220,7 @@ impl<'gc> Class<'gc> { mc, Self { name, + params: Vec::new(), super_class, attributes: ClassAttributes::empty(), protected_namespace: None, @@ -230,6 +237,23 @@ impl<'gc> Class<'gc> { ) } + /// Apply type parameters to an existing class. + /// + /// This is used to parameterize a generic type. The returned class will no + /// longer be generic. + pub fn with_type_params( + &self, + params: &[GcCell<'gc, Class<'gc>>], + mc: MutationContext<'gc, '_>, + ) -> GcCell<'gc, Class<'gc>> { + let mut new_class = self.clone(); + + new_class.params = params.to_vec(); + new_class.attributes.remove(ClassAttributes::GENERIC); + + GcCell::allocate(mc, new_class) + } + /// Set the attributes of the class (sealed/final/interface status). pub fn set_attributes(&mut self, attributes: ClassAttributes) { self.attributes = attributes; @@ -310,6 +334,7 @@ impl<'gc> Class<'gc> { activation.context.gc_context, Self { name, + params: Vec::new(), super_class, attributes, protected_namespace, @@ -392,6 +417,7 @@ impl<'gc> Class<'gc> { activation.context.gc_context, Self { name: QName::dynamic_name(name), + params: Vec::new(), super_class: None, attributes: ClassAttributes::empty(), protected_namespace: None, @@ -758,4 +784,9 @@ impl<'gc> Class<'gc> { pub fn is_interface(&self) -> bool { self.attributes.contains(ClassAttributes::INTERFACE) } + + /// Determine if this class is generic (can be specialized) + pub fn is_generic(&self) -> bool { + self.attributes.contains(ClassAttributes::GENERIC) + } }