implement Select and HasAttr

This commit is contained in:
2026-04-22 08:32:11 +08:00
parent e469d1b819
commit 21036aba46
9 changed files with 316 additions and 96 deletions
+28 -7
View File
@@ -74,6 +74,10 @@ pub trait VmContext {
pub(crate) trait VmContextExt: VmContext {
fn get_string<'a, 'gc: 'a>(&'a self, val: StrictValue<'gc>) -> Option<&'a str>;
fn get_string_id<'a, 'gc: 'a>(
&'a mut self,
val: StrictValue<'gc>,
) -> std::result::Result<StringId, NixType>;
fn convert_value(&self, val: Value) -> fix_common::Value;
}
@@ -86,6 +90,19 @@ impl<T: VmContext> VmContextExt for T {
}
}
fn get_string_id<'a, 'gc: 'a>(
&'a mut self,
val: StrictValue<'gc>,
) -> std::result::Result<StringId, NixType> {
if let Some(sid) = val.as_inline::<StringId>() {
Ok(sid)
} else if let Some(s) = val.as_gc::<NixString>().map(|ns| ns.as_ref().as_str()) {
Ok(self.intern_string(s))
} else {
Err(val.ty())
}
}
fn convert_value(&self, val: Value) -> fix_common::Value {
use fix_common::Value;
if let Some(i) = val.as_inline::<i32>() {
@@ -288,7 +305,9 @@ impl<'gc> Vm<'gc> {
#[inline(always)]
pub(crate) fn finish_type_err(&mut self, expected: NixType, got: NixType) -> Step {
self.result = Some(Err(Error::eval_error(format!("expected {expected}, got {got}"))));
self.result = Some(Err(Error::eval_error(format!(
"expected {expected}, got {got}"
))));
Step::Break(Break::Done)
}
@@ -320,8 +339,7 @@ impl<'gc> Vm<'gc> {
#[inline(always)]
#[must_use]
pub(crate) fn peek_forced(&mut self, depth: usize) -> StrictValue<'gc> {
self
.stack
self.stack
.get(self.stack.len() - depth - 1)
.expect("stack underflow")
.restrict()
@@ -531,8 +549,13 @@ impl<'gc> Vm<'gc> {
MakeEmptyAttrs => self.op_make_empty_attrs(),
SelectStatic => self.op_select_static(ctx, &mut reader, mc),
SelectDynamic => self.op_select_dynamic(ctx, &mut reader, mc),
HasAttrPathStatic => self.op_has_attr_path_static(ctx, &mut reader, mc),
HasAttrPathDynamic => self.op_has_attr_path_dynamic(ctx, &mut reader, mc),
HasAttrStatic => self.op_has_attr_static(&mut reader, mc),
HasAttrDynamic => self.op_has_attr_dynamic(ctx, &mut reader, mc),
HasAttrResolve => self.op_has_attr_resolve(),
JumpIfSelectFailed => self.op_jump_if_select_failed(&mut reader),
JumpIfSelectSucceeded => self.op_jump_if_select_succeeded(&mut reader),
HasAttr => self.op_has_attr(&mut reader),
MakeList => self.op_make_list(ctx, &mut reader, mc),
MakeEmptyList => self.op_make_empty_list(),
@@ -580,9 +603,7 @@ impl<'gc> Vm<'gc> {
match result {
Step::Continue(()) | Step::Break(Break::Force) => {}
Step::Break(Break::Done) => {
return Action::Done(
self.result.take().expect("Break::Done without result"),
);
return Action::Done(self.result.take().expect("Break::Done without result"));
}
}
}