implement string context
This commit is contained in:
@@ -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(());
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user