diff --git a/Cargo.toml b/Cargo.toml index f8d1552..a52cfcc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,8 +72,8 @@ rustls-tls-webpki-roots = [ # core deps serde_json = { version = "1.0", default-features = false, features = ["alloc"] } gc-arena = { version = "=0.4.0", default-features = false } -# netsblox-ast = { version = "=0.5.6", default-features = false } -netsblox-ast = { path = "../netsblox-ast", default-features = false } +netsblox-ast = { version = "=0.5.7", default-features = false } +# netsblox-ast = { path = "../netsblox-ast", default-features = false } num-traits = { version = "0.2.17", default-features = false } num-derive = { version = "0.4.1", default-features = false } bin-pool = { version = "0.1.1", default-features = false } diff --git a/src/bytecode.rs b/src/bytecode.rs index d15b764..b5b4ca6 100644 --- a/src/bytecode.rs +++ b/src/bytecode.rs @@ -19,7 +19,7 @@ use bin_pool::BinPool; use crate::*; use crate::meta::*; -use crate::runtime::{Color, Number, NumberError, Event, KeyCode, Property, PrintStyle, Type, CustomTypes, System}; +use crate::runtime::{Color, Number, NumberError, Event, KeyCode, Property, PrintStyle, Type, CustomTypes, System, ImageProperty, AudioProperty}; use crate::util::LosslessJoin; use crate::vecmap::VecMap; use crate::compact_str::{CompactString, ToCompactString}; @@ -413,8 +413,8 @@ pub(crate) enum Instruction<'a> { PushCostumeNumber, /// Pushes a shallow copy of the entity's list of static costumes onto the value stack. PushCostumeList, - /// Consumes 1 value, `costume`, from the value stack and pushes its name onto the value stack. - PushCostumeName, + /// Consumes 1 value, `costume`, from the value stack and pushes one of its properties onto the value stack. + PushCostumeProperty { prop: ImageProperty }, /// Consumes 1 value, `costume`, from the value stack and assigns it as the current costume. /// This can be an image or the name of a static costume on the entity. @@ -426,8 +426,8 @@ pub(crate) enum Instruction<'a> { /// Pushes a shallow copy of the entity's list of static sounds onto the value stack. PushSoundList, - /// Consumes 1 value, `sound`, from the value stack and pushes its name onto the value stack. - PushSoundName, + /// Consumes 1 value, `sound`, from the value stack and pushes one of its properties onto the value stack. + PushSoundProperty { prop: AudioProperty }, /// Consumes 1 value, `sound`, from the value stack and attempts to play it. /// This can be an audio object or the name of a static sound on the entity. @@ -517,7 +517,7 @@ macro_rules! read_write_u8_type { } )*} } -read_write_u8_type! { PrintStyle, Property, Relation, TimeQuery, BinaryOp, UnaryOp, VariadicOp, BasicType, AbortMode } +read_write_u8_type! { PrintStyle, ImageProperty, AudioProperty, Property, Relation, TimeQuery, BinaryOp, UnaryOp, VariadicOp, BasicType, AbortMode } /// encodes values as a sequence of bytes of form [1: next][7: bits] in little-endian order. /// `bytes` can be used to force a specific size (too small will panic), otherwise calculates and uses the smallest possible size. @@ -866,13 +866,13 @@ impl<'a> BinaryRead<'a> for Instruction<'a> { 119 => read_prefixed!(Instruction::PushCostume), 120 => read_prefixed!(Instruction::PushCostumeNumber), 121 => read_prefixed!(Instruction::PushCostumeList), - 122 => read_prefixed!(Instruction::PushCostumeName), + 122 => read_prefixed!(Instruction::PushCostumeProperty {} : prop), 123 => read_prefixed!(Instruction::SetCostume), 124 => read_prefixed!(Instruction::NextCostume), 125 => read_prefixed!(Instruction::PushSoundList), - 126 => read_prefixed!(Instruction::PushSoundName), + 126 => read_prefixed!(Instruction::PushSoundProperty {} : prop), 127 => read_prefixed!(Instruction::PlaySound { blocking: true }), 128 => read_prefixed!(Instruction::PlaySound { blocking: false }), @@ -1081,13 +1081,13 @@ impl BinaryWrite for Instruction<'_> { Instruction::PushCostume => append_prefixed!(119), Instruction::PushCostumeNumber => append_prefixed!(120), Instruction::PushCostumeList => append_prefixed!(121), - Instruction::PushCostumeName => append_prefixed!(122), + Instruction::PushCostumeProperty { prop } => append_prefixed!(122: prop), Instruction::SetCostume => append_prefixed!(123), Instruction::NextCostume => append_prefixed!(124), Instruction::PushSoundList => append_prefixed!(125), - Instruction::PushSoundName => append_prefixed!(126), + Instruction::PushSoundProperty { prop } => append_prefixed!(126: prop), Instruction::PlaySound { blocking: true } => append_prefixed!(127), Instruction::PlaySound { blocking: false } => append_prefixed!(128), @@ -1566,9 +1566,9 @@ impl<'a: 'b, 'b> ByteCodeBuilder<'a, 'b> { ast::ExprKind::Costume => self.ins.push(Instruction::PushCostume.into()), ast::ExprKind::CostumeNumber => self.ins.push(Instruction::PushCostumeNumber.into()), ast::ExprKind::CostumeList => self.ins.push(Instruction::PushCostumeList.into()), - ast::ExprKind::CostumeName { costume } => self.append_simple_ins(entity, &[costume], Instruction::PushCostumeName)?, + ast::ExprKind::CostumeName { costume } => self.append_simple_ins(entity, &[costume], Instruction::PushCostumeProperty { prop: ImageProperty::Name })?, ast::ExprKind::SoundList => self.ins.push(Instruction::PushSoundList.into()), - ast::ExprKind::SoundName { sound } => self.append_simple_ins(entity, &[sound], Instruction::PushSoundName)?, + ast::ExprKind::SoundName { sound } => self.append_simple_ins(entity, &[sound], Instruction::PushSoundProperty { prop: AudioProperty::Name })?, ast::ExprKind::Size => self.ins.push(Instruction::PushProperty { prop: Property::Size }.into()), ast::ExprKind::IsVisible => self.ins.push(Instruction::PushProperty { prop: Property::Visible }.into()), ast::ExprKind::Entity { trans_name, .. } => self.ins.push(Instruction::PushEntity { name: trans_name }.into()), diff --git a/src/process.rs b/src/process.rs index 36e53bf..7607292 100644 --- a/src/process.rs +++ b/src/process.rs @@ -1230,12 +1230,23 @@ impl<'gc, C: CustomTypes, S: System> Process<'gc, C, S> { self.value_stack.push(Value::List(Gc::new(mc, RefLock::new(entity.costume_list.iter().map(|x| Value::Image(x.1.clone())).collect())))); self.pos = aft_pos; } - Instruction::PushCostumeName => { - let costume = self.value_stack.pop().unwrap(); - self.value_stack.push(match costume { - Value::String(x) if x.is_empty() => empty_string().into(), - Value::Image(x) => Rc::new(x.name.clone()).into(), + Instruction::PushCostumeProperty { prop } => { + let mut entity_raw = self.call_stack.last().unwrap().entity.borrow_mut(mc); + let entity = &mut *entity_raw; + + let costume = match self.value_stack.pop().unwrap() { + Value::String(x) => match x.as_str() { + "" => None, + x => match entity.costume_list.get(x) { + Some(x) => Some(x.clone()), + None => return Err(ErrorCause::UndefinedCostume { name: x.into() }), + } + } + Value::Image(x) => Some(x), x => return Err(ErrorCause::ConversionError { got: x.get_type(), expected: Type::Image }), + }; + self.value_stack.push(match prop { + ImageProperty::Name => costume.map(|x| Rc::new(x.name.clone())).unwrap_or_else(empty_string).into(), }); self.pos = aft_pos; } @@ -1297,7 +1308,7 @@ impl<'gc, C: CustomTypes, S: System> Process<'gc, C, S> { self.value_stack.push(Value::List(Gc::new(mc, RefLock::new(entity.sound_list.iter().map(|x| Value::Audio(x.1.clone())).collect())))); self.pos = aft_pos; } - Instruction::PushSoundName => { + Instruction::PushSoundProperty { prop } => { let entity_raw = self.call_stack.last().unwrap().entity.borrow(); let entity = &*entity_raw; @@ -1309,9 +1320,9 @@ impl<'gc, C: CustomTypes, S: System> Process<'gc, C, S> { } x => return Err(ErrorCause::ConversionError { got: x.get_type(), expected: Type::Audio }), }; - - self.value_stack.push(Rc::new(sound.name.clone()).into()); - + self.value_stack.push(match prop { + AudioProperty::Name => Rc::new(sound.name.clone()).into(), + }); self.pos = aft_pos; } Instruction::PlaySound { blocking } => { diff --git a/src/runtime.rs b/src/runtime.rs index ed64f71..60d6be7 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -293,6 +293,17 @@ fn test_color_rgb_to_hsv() { assert_round_trip!(Color { r: 0, g: 0, b: 10, a: 0 }); } +#[derive(Debug, Clone, Copy, FromPrimitive)] +#[repr(u8)] +pub enum ImageProperty { + Name, +} +#[derive(Debug, Clone, Copy, FromPrimitive)] +#[repr(u8)] +pub enum AudioProperty { + Name, +} + #[derive(Debug, Clone, Copy, FromPrimitive)] #[repr(u8)] pub enum Property { diff --git a/src/test/project.rs b/src/test/project.rs index 042b7b2..9bd28ed 100644 --- a/src/test/project.rs +++ b/src/test/project.rs @@ -508,9 +508,9 @@ fn test_proj_costume_names() { "", "", "IndexOutOfBounds { index: 0, len: 3 }", - ["squiggle", "squiggle", "squiggle", "squiggle", "squiggle", 1], - ["zap", "zap", "zap", "zap", "zap", 3], - ["zip", "zip", "zip", "zip", "zip", 2], + ["squiggle", "squiggle", "squiggle", "squiggle", "squiggle", 1, "squiggle", "squiggle"], + ["zap", "zap", "zap", "zap", "zap", 3, "zap", "zap"], + ["zip", "zip", "zip", "zip", "zip", 2, "zip", "zip"], ])).unwrap()); assert_values_eq(&global_context.globals.lookup("res").unwrap().get(), &expected, 1e-10, "res"); }); @@ -526,9 +526,9 @@ fn test_proj_sound_names() { let global_context = global_context.borrow(); let expected = Value::from_simple(mc, SimpleValue::from_json(json!([ - ["boop", "boop", "boop"], - ["bop", "bop", "bop"], - ["swoop", "swoop", "swoop"], + ["boop", "boop", "boop", "boop"], + ["bop", "bop", "bop", "bop"], + ["swoop", "swoop", "swoop", "swoop"], ])).unwrap()); assert_values_eq(&global_context.globals.lookup("gtf").unwrap().get(), &expected, 1e-10, "gtf"); }); diff --git a/src/test/projects/costume-names.xml b/src/test/projects/costume-names.xml index 6e4edee..0235b9d 100644 --- a/src/test/projects/costume-names.xml +++ b/src/test/projects/costume-names.xml @@ -1 +1 @@ -messagemsgerrsquiggleSprite(2)#1Sprite(2)#1zapSprite(2)#1Sprite(2)#1zipSprite(2)#1Sprite(2)#1 \ No newline at end of file +messagemsgerrsquiggleSprite(2)#1Sprite(2)#1squigglesquigglezapSprite(2)#1Sprite(2)#1zapzapzipSprite(2)#1Sprite(2)#1zipzip \ No newline at end of file diff --git a/src/test/projects/sound-names.xml b/src/test/projects/sound-names.xml index 3f7f104..b642b57 100644 --- a/src/test/projects/sound-names.xml +++ b/src/test/projects/sound-names.xml @@ -1 +1 @@ -messagemsgbop,boop,boopboop,bop,bopswoop,swoop,swoop \ No newline at end of file +messagemsg \ No newline at end of file