diff --git a/interpreter/src/ir.rs b/interpreter/src/ir.rs index 0efc859..1f4be17 100644 --- a/interpreter/src/ir.rs +++ b/interpreter/src/ir.rs @@ -224,6 +224,7 @@ impl OpCode { | Self::Divide | Self::Raise | Self::Modulo + | Self::Concat ) } diff --git a/interpreter/src/types.rs b/interpreter/src/types.rs index b61a5b7..3e46afb 100644 --- a/interpreter/src/types.rs +++ b/interpreter/src/types.rs @@ -1,6 +1,8 @@ use std::{ borrow::Cow, + fmt::Display, hash::Hash, + io::Write, mem::discriminant, ops::{Add, Div, Mul, Sub}, }; @@ -62,6 +64,26 @@ impl Value<'_> { _ => 0., } } + + pub fn write_string(&self, f: &mut Vec) { + match self { + Self::String(s) | Self::Regex(s) => f.extend_from_slice(s), + Self::Float(n) => write!(f, "{n}").unwrap(), + &Self::Bool(false) => f.push(b'0'), + &Self::Bool(true) => f.push(b'1'), + Self::Array(_) => panic!("Attempted to use array in scalar context!"), + _ => {} + } + } + + pub fn string_size_hint(&self) -> usize { + match self { + Self::String(s) | Self::Regex(s) => s.len(), + Self::Float(_) => 2, + Self::Bool(_) => 1, + _ => 0, + } + } } impl<'a> Add for &'_ Value<'a> { @@ -109,3 +131,17 @@ impl Hash for Value<'_> { } } } + +impl Display for Value<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Value::Float(n) => <_ as Display>::fmt(n, f), + Value::String(s) => write!(f, "{:?}", String::from_utf8_lossy(s)), + Value::Regex(s) => write!(f, "/{}/", String::from_utf8_lossy(s)), + &Value::Bool(b) => write!(f, "{}", b as usize), + Value::Array(_) => write!(f, "array"), + Value::Untyped => write!(f, "untyped"), + Value::Unassigned => write!(f, "unassigned"), + } + } +} diff --git a/interpreter/src/vm.rs b/interpreter/src/vm.rs index fee5280..2da0a87 100644 --- a/interpreter/src/vm.rs +++ b/interpreter/src/vm.rs @@ -1,6 +1,7 @@ use std::{ fmt::{self, Display}, mem::replace, + vec::Vec as StdVec, }; use ahash::RandomState; @@ -117,6 +118,14 @@ impl Interpreter<'_> { OpCode::Subtract => lhs - rhs, OpCode::Multiply => lhs * rhs, OpCode::Divide => lhs / rhs, + OpCode::Concat => { + let mut buf = StdVec::with_capacity( + lhs.string_size_hint() + rhs.string_size_hint(), + ); + lhs.write_string(&mut buf); + rhs.write_string(&mut buf); + Value::String(buf.into()) + } _ => todo!(), } }; @@ -203,7 +212,7 @@ impl Display for Registers<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Registers:")?; let n = self.0.len().checked_ilog10().unwrap_or(0) as usize + 1; - fmt_list(f, self.0.iter(), |f, i, e| write!(f, "r{i:0n$} = {e:?}")) + fmt_list(f, self.0.iter(), |f, i, e| write!(f, "r{i:0n$} = {e}")) } } @@ -211,7 +220,7 @@ impl Display for SymbolTable<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Symbols:")?; fmt_list(f, self.user.iter(), |f, i, (k, v)| { - write!(f, "user[{i}] @ {k} = {v:?}") + write!(f, "user[{i}] @ {k} = {v}") }) } } @@ -219,7 +228,7 @@ impl Display for SymbolTable<'_> { impl Display for Consts<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Consts:")?; - fmt_list(f, self.0.iter(), |f, i, e| write!(f, "mem[{i}] = {e:?}")) + fmt_list(f, self.0.iter(), |f, i, e| write!(f, "mem[{i}] = {e}")) } }