@@ -99,6 +99,16 @@ fn jit_supported_instruction(instr: &RegInstr) -> bool {
9999 | RegInstr::MakeList { .. }
100100 | RegInstr::MakeObject { .. }
101101 | RegInstr::MakeMap { .. }
102+ | RegInstr::MakeSome { .. }
103+ | RegInstr::LoadNone { .. }
104+ | RegInstr::MakeClosure { .. }
105+ | RegInstr::MatchOption { .. }
106+ | RegInstr::MatchResult { .. }
107+ | RegInstr::MatchVariant { .. }
108+ | RegInstr::MatchMapGet { .. }
109+ | RegInstr::UnwrapSome { .. }
110+ | RegInstr::UnwrapVariantValue { .. }
111+ | RegInstr::RuntimeError { .. }
102112 | RegInstr::AddInt { .. }
103113 | RegInstr::SubInt { .. }
104114 | RegInstr::MulInt { .. }
@@ -5070,6 +5080,127 @@ impl RegVm {
50705080 ip = *target;
50715081 }
50725082 }
5083+ RegInstr::MakeSome { dst, value } => {
5084+ let value = self.reg(base + *value).clone();
5085+ self.set_reg(base + *dst, VmValue::OptionSome(Box::new(value)));
5086+ }
5087+ RegInstr::LoadNone { dst } => {
5088+ self.set_reg(base + *dst, VmValue::OptionNone);
5089+ }
5090+ RegInstr::MakeClosure {
5091+ dst,
5092+ function: callee,
5093+ captures,
5094+ } => {
5095+ let mut captured = Vec::with_capacity(captures.len());
5096+ for reg in captures {
5097+ captured.push(self.reg(base + *reg).clone());
5098+ }
5099+ self.set_reg(
5100+ base + *dst,
5101+ VmValue::Closure(Rc::new(VmClosure {
5102+ function: *callee,
5103+ captures: captured,
5104+ })),
5105+ );
5106+ }
5107+ RegInstr::MatchOption {
5108+ src,
5109+ some_ip,
5110+ none_ip,
5111+ } => match self.reg(base + *src) {
5112+ VmValue::OptionSome(_) => ip = *some_ip,
5113+ VmValue::OptionNone => ip = *none_ip,
5114+ other => {
5115+ return Err(EvalError::Runtime(format!(
5116+ "reg VM Option match expected Option, got `{}`.",
5117+ other.display()
5118+ )));
5119+ }
5120+ },
5121+ RegInstr::MatchResult { src, ok_ip, err_ip } => match self.reg(base + *src) {
5122+ VmValue::Variant(data) if data.name.as_ref() == "Ok" => ip = *ok_ip,
5123+ VmValue::Variant(data) if data.name.as_ref() == "Err" => ip = *err_ip,
5124+ other => {
5125+ return Err(EvalError::Runtime(format!(
5126+ "reg VM Result match expected Result, got `{}`.",
5127+ other.display()
5128+ )));
5129+ }
5130+ },
5131+ RegInstr::MatchVariant {
5132+ src,
5133+ expected,
5134+ match_ip,
5135+ else_ip,
5136+ } => match self.reg(base + *src) {
5137+ VmValue::Variant(data) if data.name.as_ref() == expected.as_str() => {
5138+ ip = *match_ip
5139+ }
5140+ VmValue::Variant(_) => ip = *else_ip,
5141+ other => {
5142+ return Err(EvalError::Runtime(format!(
5143+ "reg VM variant match expected `{expected}`, got `{}`.",
5144+ other.display()
5145+ )));
5146+ }
5147+ },
5148+ RegInstr::MatchMapGet {
5149+ map,
5150+ key,
5151+ value_dst,
5152+ some_ip,
5153+ none_ip,
5154+ } => {
5155+ let map = expect_map_ref(self.reg(base + *map))?;
5156+ let key = map_key_from_value(self.reg(base + *key))?;
5157+ if let Some(value) = map.borrow().get(&key).cloned() {
5158+ self.set_reg(base + *value_dst, value);
5159+ ip = *some_ip;
5160+ } else {
5161+ ip = *none_ip;
5162+ }
5163+ }
5164+ RegInstr::UnwrapSome { dst, src } => {
5165+ let value = match self.reg(base + *src) {
5166+ VmValue::OptionSome(value) => (**value).clone(),
5167+ other => {
5168+ return Err(EvalError::Runtime(format!(
5169+ "reg VM Some binding expected Some, got `{}`.",
5170+ other.display()
5171+ )));
5172+ }
5173+ };
5174+ self.set_reg(base + *dst, value);
5175+ }
5176+ RegInstr::UnwrapVariantValue { dst, src, expected } => {
5177+ let value = match self.reg(base + *src) {
5178+ VmValue::Variant(data) if data.name.as_ref() == expected.as_str() => data
5179+ .fields
5180+ .get("value")
5181+ .cloned()
5182+ .or_else(|| {
5183+ (data.fields.len() == 1)
5184+ .then(|| data.fields.values().next().cloned())
5185+ .flatten()
5186+ })
5187+ .ok_or_else(|| {
5188+ EvalError::Runtime(format!(
5189+ "reg VM `{expected}` variant is missing value."
5190+ ))
5191+ })?,
5192+ other => {
5193+ return Err(EvalError::Runtime(format!(
5194+ "reg VM expected `{expected}` variant, got `{}`.",
5195+ other.display()
5196+ )));
5197+ }
5198+ };
5199+ self.set_reg(base + *dst, value);
5200+ }
5201+ RegInstr::RuntimeError { message } => {
5202+ return Err(EvalError::Runtime(message.clone()));
5203+ }
50735204 RegInstr::Return { src } => return Ok(self.take_reg(base + *src)),
50745205 // Eligibility (`jit_supported_instruction`) guarantees only the
50755206 // instructions above reach here. A mismatch would be an internal
0 commit comments