feat(tvix/value): introduce string representation with &'static str
For cases where the strings are statically known (such as the oft-occuring name/value), this can be a useful optimisation. It's also much more convenient in tests. Change-Id: Ie462b684805bd4986ea5e85ca4bff663bc2d3c3c Reviewed-on: https://cl.tvl.fyi/c/depot/+/6111 Tested-by: BuildkiteCI Reviewed-by: eta <tvl@eta.st>
This commit is contained in:
parent
c7ba2dec04
commit
6dc9ca5723
4 changed files with 44 additions and 26 deletions
|
@ -111,7 +111,7 @@ impl Compiler {
|
||||||
rnix::StrPart::Ast(node) => self.compile(node)?,
|
rnix::StrPart::Ast(node) => self.compile(node)?,
|
||||||
|
|
||||||
rnix::StrPart::Literal(lit) => {
|
rnix::StrPart::Literal(lit) => {
|
||||||
let idx = self.chunk.add_constant(Value::String(NixString(lit)));
|
let idx = self.chunk.add_constant(Value::String(lit.into()));
|
||||||
self.chunk.add_op(OpCode::OpConstant(idx));
|
self.chunk.add_op(OpCode::OpConstant(idx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,9 +206,9 @@ impl Compiler {
|
||||||
let ident = rnix::types::Ident::cast(fragment).unwrap();
|
let ident = rnix::types::Ident::cast(fragment).unwrap();
|
||||||
|
|
||||||
// TODO(tazjin): intern!
|
// TODO(tazjin): intern!
|
||||||
let idx = self
|
let idx = self.chunk.add_constant(Value::String(NixString::Heap(
|
||||||
.chunk
|
ident.as_str().to_string(),
|
||||||
.add_constant(Value::String(NixString(ident.as_str().to_string())));
|
)));
|
||||||
self.chunk.add_op(OpCode::OpConstant(idx));
|
self.chunk.add_op(OpCode::OpConstant(idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,14 +71,8 @@ impl NixAttrs {
|
||||||
|
|
||||||
NixAttrs::KV { name, value } => {
|
NixAttrs::KV { name, value } => {
|
||||||
*self = NixAttrs::Map(BTreeMap::from([
|
*self = NixAttrs::Map(BTreeMap::from([
|
||||||
(
|
("name".into(), std::mem::replace(name, Value::Blackhole)),
|
||||||
NixString("name".into()),
|
("value".into(), std::mem::replace(value, Value::Blackhole)),
|
||||||
std::mem::replace(name, Value::Blackhole),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
NixString("value".into()),
|
|
||||||
std::mem::replace(value, Value::Blackhole),
|
|
||||||
),
|
|
||||||
]));
|
]));
|
||||||
self.map_mut()
|
self.map_mut()
|
||||||
}
|
}
|
||||||
|
@ -155,14 +149,14 @@ impl NixAttrs {
|
||||||
fn attempt_optimise_kv(slice: &mut [Value]) -> Option<NixAttrs> {
|
fn attempt_optimise_kv(slice: &mut [Value]) -> Option<NixAttrs> {
|
||||||
let (name_idx, value_idx) = {
|
let (name_idx, value_idx) = {
|
||||||
match (&slice[2], &slice[0]) {
|
match (&slice[2], &slice[0]) {
|
||||||
(Value::String(NixString(s1)), Value::String(NixString(s2)))
|
(Value::String(s1), Value::String(s2))
|
||||||
if (s1 == "name" && s2 == "value") =>
|
if (*s1 == NixString::NAME && *s2 == NixString::VALUE) =>
|
||||||
{
|
{
|
||||||
(3, 1)
|
(3, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
(Value::String(NixString(s1)), Value::String(NixString(s2)))
|
(Value::String(s1), Value::String(s2))
|
||||||
if (s1 == "value" && s2 == "name") =>
|
if (*s1 == NixString::VALUE && *s2 == NixString::NAME) =>
|
||||||
{
|
{
|
||||||
(1, 3)
|
(1, 3)
|
||||||
}
|
}
|
||||||
|
@ -189,7 +183,7 @@ fn set_attr(attrs: &mut NixAttrs, key: NixString, value: Value) -> EvalResult<()
|
||||||
match entry {
|
match entry {
|
||||||
std::collections::btree_map::Entry::Occupied(entry) => {
|
std::collections::btree_map::Entry::Occupied(entry) => {
|
||||||
return Err(Error::DuplicateAttrsKey {
|
return Err(Error::DuplicateAttrsKey {
|
||||||
key: entry.key().0.clone(),
|
key: entry.key().as_str().to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,7 +248,7 @@ fn set_nested_attr(
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::DuplicateAttrsKey {
|
return Err(Error::DuplicateAttrsKey {
|
||||||
key: entry.key().0.clone(),
|
key: entry.key().as_str().to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,16 +4,40 @@ use std::fmt::Display;
|
||||||
/// backing implementations.
|
/// backing implementations.
|
||||||
|
|
||||||
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct NixString(pub String);
|
pub enum NixString {
|
||||||
|
Static(&'static str),
|
||||||
|
Heap(String),
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for NixString {
|
impl Display for NixString {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.write_str(self.0.as_str())
|
match self {
|
||||||
|
NixString::Static(s) => f.write_str(s),
|
||||||
|
NixString::Heap(s) => f.write_str(s),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&str> for NixString {
|
impl From<&'static str> for NixString {
|
||||||
fn from(s: &str) -> Self {
|
fn from(s: &'static str) -> Self {
|
||||||
NixString(s.to_string())
|
NixString::Static(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for NixString {
|
||||||
|
fn from(s: String) -> Self {
|
||||||
|
NixString::Heap(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NixString {
|
||||||
|
pub const NAME: Self = NixString::Static("name");
|
||||||
|
pub const VALUE: Self = NixString::Static("value");
|
||||||
|
|
||||||
|
pub fn as_str(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
NixString::Static(s) => s,
|
||||||
|
NixString::Heap(s) => s,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
chunk::Chunk,
|
chunk::Chunk,
|
||||||
errors::{Error, EvalResult},
|
errors::{Error, EvalResult},
|
||||||
opcode::OpCode,
|
opcode::OpCode,
|
||||||
value::{NixAttrs, NixList, NixString, Value},
|
value::{NixAttrs, NixList, Value},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct VM {
|
pub struct VM {
|
||||||
|
@ -159,10 +159,10 @@ impl VM {
|
||||||
let mut out = String::new();
|
let mut out = String::new();
|
||||||
|
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
out.push_str(&self.pop().as_string()?.0);
|
out.push_str(&self.pop().as_string()?.as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.push(Value::String(NixString(out)));
|
self.push(Value::String(out.into()));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue