implement string context

This commit is contained in:
2026-05-17 17:02:49 +08:00
parent 9a17990d5e
commit d98e389606
11 changed files with 698 additions and 224 deletions
+7 -1
View File
@@ -33,7 +33,13 @@ impl<'gc> crate::Vm<'gc> {
return Step::Continue(());
}
if let (Some(ls), Some(rs)) = (ctx.get_string(lhs), ctx.get_string_or_path(rhs)) {
let ns = Gc::new(mc, crate::NixString::new(format!("{ls}{rs}")));
let merged = ctx
.get_string_context(lhs)
.merge(ctx.get_string_context(rhs));
let ns = Gc::new(
mc,
crate::NixString::with_context(format!("{ls}{rs}"), merged),
);
self.push(Value::new_gc(ns));
return Step::Continue(());
}
+22 -4
View File
@@ -1,6 +1,8 @@
use std::path::PathBuf;
use fix_abstract_vm::{AttrSet, NixString, Path, StrictValue, canon_path_str};
use fix_abstract_vm::{
AttrSet, NixString, Path, StrictValue, StringContext, canon_path_str
};
use fix_builtins::BuiltinId;
use fix_common::StringId;
use fix_error::Error;
@@ -89,29 +91,45 @@ impl<'gc> crate::Vm<'gc> {
&mut self,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
_mc: &gc_arena::Mutation<'gc>,
mc: &gc_arena::Mutation<'gc>,
) -> Step {
let count = reader.read_u16() as usize;
let _force_string = reader.read_u8() != 0;
let mut total_len = 0;
let mut has_any_context = false;
for i in 0..count {
let val = self.peek_forced(count - 1 - i);
let s = ctx.get_string(val).expect("coerced");
total_len += s.len();
if !ctx.get_string_context(val).is_empty() {
has_any_context = true;
}
}
let mut result = String::with_capacity(total_len);
let mut merged = StringContext::new();
for i in 0..count {
let val = self.peek_forced(count - 1 - i);
let s = ctx.get_string(val).expect("coerced");
result.push_str(s);
if has_any_context {
let ctx = ctx.get_string_context(val);
if !ctx.is_empty() {
merged = merged.merge(ctx);
}
}
}
self.stack.truncate(self.stack.len() - count);
let sid = ctx.intern_string(result);
self.push(Value::new_inline(sid));
if merged.is_empty() {
let sid = ctx.intern_string(result);
self.push(Value::new_inline(sid));
} else {
let ns = gc_arena::Gc::new(mc, NixString::with_context(result, merged));
self.push(Value::new_gc(ns));
}
Step::Continue(())
}