mirror of
https://github.com/duhanbalci/dexpr.git
synced 2026-07-01 16:19:16 +00:00
perf improvements
This commit is contained in:
@@ -4,6 +4,7 @@ use indexmap::IndexMap;
|
|||||||
use rust_decimal::Decimal;
|
use rust_decimal::Decimal;
|
||||||
use rust_decimal_macros::dec;
|
use rust_decimal_macros::dec;
|
||||||
use smol_str::SmolStr;
|
use smol_str::SmolStr;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
/// Helper: compile source to bytecode
|
/// Helper: compile source to bytecode
|
||||||
fn compile(source: &str) -> Vec<u8> {
|
fn compile(source: &str) -> Vec<u8> {
|
||||||
@@ -18,7 +19,7 @@ fn sample_object(n: usize) -> Value {
|
|||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
map.insert(SmolStr::new(format!("field{}", i)), Value::Number(Decimal::from(i)));
|
map.insert(SmolStr::new(format!("field{}", i)), Value::Number(Decimal::from(i)));
|
||||||
}
|
}
|
||||||
Value::Object(Box::new(map))
|
Value::Object(Rc::new(map))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn criterion_benchmark(c: &mut Criterion) {
|
pub fn criterion_benchmark(c: &mut Criterion) {
|
||||||
@@ -110,7 +111,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||||||
// StringList method — clone entire Vec per call
|
// StringList method — clone entire Vec per call
|
||||||
c.bench_function("vm_strlist_method_length", |b| {
|
c.bench_function("vm_strlist_method_length", |b| {
|
||||||
let bytecode = compile("items.length()");
|
let bytecode = compile("items.length()");
|
||||||
let items = Value::StringList(Box::new((0..50).map(|i| SmolStr::new(format!("item{}", i))).collect()));
|
let items = Value::StringList(Rc::new((0..50).map(|i| SmolStr::new(format!("item{}", i))).collect()));
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let mut vm = VM::new(&bytecode);
|
let mut vm = VM::new(&bytecode);
|
||||||
vm.set_global("items", items.clone());
|
vm.set_global("items", items.clone());
|
||||||
@@ -120,7 +121,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||||||
|
|
||||||
c.bench_function("vm_numlist_method_sum", |b| {
|
c.bench_function("vm_numlist_method_sum", |b| {
|
||||||
let bytecode = compile("nums.sum()");
|
let bytecode = compile("nums.sum()");
|
||||||
let nums = Value::NumberList(Box::new((0..100).map(Decimal::from).collect()));
|
let nums = Value::NumberList(Rc::new((0..100).map(Decimal::from).collect()));
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let mut vm = VM::new(&bytecode);
|
let mut vm = VM::new(&bytecode);
|
||||||
vm.set_global("nums", nums.clone());
|
vm.set_global("nums", nums.clone());
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use indexmap::IndexMap;
|
|||||||
use rust_decimal::Decimal;
|
use rust_decimal::Decimal;
|
||||||
use smol_str::SmolStr;
|
use smol_str::SmolStr;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
/// Value type for the dExpr language
|
/// Value type for the dExpr language
|
||||||
#[derive(Debug, Clone, PartialEq, Default)]
|
#[derive(Debug, Clone, PartialEq, Default)]
|
||||||
@@ -11,9 +12,9 @@ pub enum Value {
|
|||||||
Number(Decimal),
|
Number(Decimal),
|
||||||
String(SmolStr),
|
String(SmolStr),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
NumberList(Box<Vec<Decimal>>),
|
NumberList(Rc<Vec<Decimal>>),
|
||||||
StringList(Box<Vec<SmolStr>>),
|
StringList(Rc<Vec<SmolStr>>),
|
||||||
Object(Box<IndexMap<SmolStr, Value>>),
|
Object(Rc<IndexMap<SmolStr, Value>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Type tag constants for serialization
|
/// Type tag constants for serialization
|
||||||
@@ -209,19 +210,19 @@ impl From<SmolStr> for Value {
|
|||||||
|
|
||||||
impl From<Vec<Decimal>> for Value {
|
impl From<Vec<Decimal>> for Value {
|
||||||
fn from(v: Vec<Decimal>) -> Self {
|
fn from(v: Vec<Decimal>) -> Self {
|
||||||
Value::NumberList(Box::new(v))
|
Value::NumberList(Rc::new(v))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<SmolStr>> for Value {
|
impl From<Vec<SmolStr>> for Value {
|
||||||
fn from(v: Vec<SmolStr>) -> Self {
|
fn from(v: Vec<SmolStr>) -> Self {
|
||||||
Value::StringList(Box::new(v))
|
Value::StringList(Rc::new(v))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<IndexMap<SmolStr, Value>> for Value {
|
impl From<IndexMap<SmolStr, Value>> for Value {
|
||||||
fn from(m: IndexMap<SmolStr, Value>) -> Self {
|
fn from(m: IndexMap<SmolStr, Value>) -> Self {
|
||||||
Value::Object(Box::new(m))
|
Value::Object(Rc::new(m))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,7 +293,7 @@ impl Value {
|
|||||||
list.push(Decimal::deserialize(decimal_bytes));
|
list.push(Decimal::deserialize(decimal_bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((Value::NumberList(Box::new(list)), pos))
|
Ok((Value::NumberList(Rc::new(list)), pos))
|
||||||
}
|
}
|
||||||
TYPE_STRING_LIST => {
|
TYPE_STRING_LIST => {
|
||||||
if bytes.len() < pos + 2 {
|
if bytes.len() < pos + 2 {
|
||||||
@@ -321,7 +322,7 @@ impl Value {
|
|||||||
list.push(s.into());
|
list.push(s.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((Value::StringList(Box::new(list)), pos))
|
Ok((Value::StringList(Rc::new(list)), pos))
|
||||||
}
|
}
|
||||||
TYPE_OBJECT => {
|
TYPE_OBJECT => {
|
||||||
if bytes.len() < pos + 2 {
|
if bytes.len() < pos + 2 {
|
||||||
@@ -354,7 +355,7 @@ impl Value {
|
|||||||
map.insert(key.into(), val);
|
map.insert(key.into(), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((Value::Object(Box::new(map)), pos))
|
Ok((Value::Object(Rc::new(map)), pos))
|
||||||
}
|
}
|
||||||
_ => Err(format!("Unknown type tag: {}", type_tag)),
|
_ => Err(format!("Unknown type tag: {}", type_tag)),
|
||||||
}
|
}
|
||||||
@@ -407,7 +408,7 @@ impl Value {
|
|||||||
serde_json::Value::String(s) => Ok(Value::String(SmolStr::new(s))),
|
serde_json::Value::String(s) => Ok(Value::String(SmolStr::new(s))),
|
||||||
serde_json::Value::Array(arr) => {
|
serde_json::Value::Array(arr) => {
|
||||||
if arr.is_empty() {
|
if arr.is_empty() {
|
||||||
return Ok(Value::StringList(Box::new(Vec::new())));
|
return Ok(Value::StringList(Rc::new(Vec::new())));
|
||||||
}
|
}
|
||||||
// Check if all elements are the same type
|
// Check if all elements are the same type
|
||||||
let first = &arr[0];
|
let first = &arr[0];
|
||||||
@@ -418,12 +419,12 @@ impl Value {
|
|||||||
nums.push(n);
|
nums.push(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Value::NumberList(Box::new(nums)))
|
Ok(Value::NumberList(Rc::new(nums)))
|
||||||
} else if first.is_string() && arr.iter().all(|v| v.is_string()) {
|
} else if first.is_string() && arr.iter().all(|v| v.is_string()) {
|
||||||
let strings: Vec<SmolStr> = arr.iter()
|
let strings: Vec<SmolStr> = arr.iter()
|
||||||
.filter_map(|v| v.as_str().map(SmolStr::new))
|
.filter_map(|v| v.as_str().map(SmolStr::new))
|
||||||
.collect();
|
.collect();
|
||||||
Ok(Value::StringList(Box::new(strings)))
|
Ok(Value::StringList(Rc::new(strings)))
|
||||||
} else {
|
} else {
|
||||||
Err("Arrays must contain all numbers or all strings".to_string())
|
Err("Arrays must contain all numbers or all strings".to_string())
|
||||||
}
|
}
|
||||||
@@ -433,7 +434,7 @@ impl Value {
|
|||||||
for (k, v) in obj {
|
for (k, v) in obj {
|
||||||
map.insert(SmolStr::new(k), Self::from_json_value(v)?);
|
map.insert(SmolStr::new(k), Self::from_json_value(v)?);
|
||||||
}
|
}
|
||||||
Ok(Value::Object(Box::new(map)))
|
Ok(Value::Object(Rc::new(map)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
//! use indexmap::IndexMap;
|
//! use indexmap::IndexMap;
|
||||||
//! use smol_str::SmolStr;
|
//! use smol_str::SmolStr;
|
||||||
//! use rust_decimal_macros::dec;
|
//! use rust_decimal_macros::dec;
|
||||||
|
//! use std::rc::Rc;
|
||||||
//!
|
//!
|
||||||
//! let mut info = LanguageInfo::builtin();
|
//! let mut info = LanguageInfo::builtin();
|
||||||
//!
|
//!
|
||||||
@@ -24,7 +25,7 @@
|
|||||||
//! let mut customer = IndexMap::new();
|
//! let mut customer = IndexMap::new();
|
||||||
//! customer.insert(SmolStr::new("name"), Value::String("Alice".into()));
|
//! customer.insert(SmolStr::new("name"), Value::String("Alice".into()));
|
||||||
//! customer.insert(SmolStr::new("age"), Value::Number(dec!(30)));
|
//! customer.insert(SmolStr::new("age"), Value::Number(dec!(30)));
|
||||||
//! info.add_value("customer", &Value::Object(Box::new(customer)), None);
|
//! info.add_value("customer", &Value::Object(Rc::new(customer)), None);
|
||||||
//! info.add_value("price", &Value::Number(dec!(100)), None);
|
//! info.add_value("price", &Value::Number(dec!(100)), None);
|
||||||
//!
|
//!
|
||||||
//! let json = info.to_json();
|
//! let json = info.to_json();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use crate::ast::value::Value;
|
use crate::ast::value::Value;
|
||||||
use rust_decimal::{prelude::ToPrimitive, Decimal};
|
use rust_decimal::{prelude::ToPrimitive, Decimal};
|
||||||
use smol_str::{SmolStr, StrExt};
|
use smol_str::{SmolStr, StrExt};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use super::error::VMError;
|
use super::error::VMError;
|
||||||
use super::vm::VM;
|
use super::vm::VM;
|
||||||
@@ -72,7 +73,7 @@ impl<'a> VM<'a> {
|
|||||||
match &args[0] {
|
match &args[0] {
|
||||||
Value::String(delim) => {
|
Value::String(delim) => {
|
||||||
let parts: Vec<SmolStr> = s.split(delim.as_str()).map(SmolStr::new).collect();
|
let parts: Vec<SmolStr> = s.split(delim.as_str()).map(SmolStr::new).collect();
|
||||||
Ok(Value::StringList(Box::new(parts)))
|
Ok(Value::StringList(Rc::new(parts)))
|
||||||
}
|
}
|
||||||
_ => Err(VMError::RuntimeError(
|
_ => Err(VMError::RuntimeError(
|
||||||
"split() requires a string delimiter".to_string(),
|
"split() requires a string delimiter".to_string(),
|
||||||
@@ -263,7 +264,7 @@ impl<'a> VM<'a> {
|
|||||||
} else {
|
} else {
|
||||||
list.len()
|
list.len()
|
||||||
};
|
};
|
||||||
Ok(Value::StringList(Box::new(list[start..end].to_vec())))
|
Ok(Value::StringList(Rc::new(list[start..end].to_vec())))
|
||||||
}
|
}
|
||||||
_ => Err(VMError::RuntimeError("slice() requires a number index".to_string())),
|
_ => Err(VMError::RuntimeError("slice() requires a number index".to_string())),
|
||||||
}
|
}
|
||||||
@@ -271,12 +272,12 @@ impl<'a> VM<'a> {
|
|||||||
"reverse" => {
|
"reverse" => {
|
||||||
let mut reversed = list.to_vec();
|
let mut reversed = list.to_vec();
|
||||||
reversed.reverse();
|
reversed.reverse();
|
||||||
Ok(Value::StringList(Box::new(reversed)))
|
Ok(Value::StringList(Rc::new(reversed)))
|
||||||
}
|
}
|
||||||
"sort" => {
|
"sort" => {
|
||||||
let mut sorted = list.to_vec();
|
let mut sorted = list.to_vec();
|
||||||
sorted.sort();
|
sorted.sort();
|
||||||
Ok(Value::StringList(Box::new(sorted)))
|
Ok(Value::StringList(Rc::new(sorted)))
|
||||||
}
|
}
|
||||||
"join" => {
|
"join" => {
|
||||||
let delim = if args.is_empty() {
|
let delim = if args.is_empty() {
|
||||||
@@ -368,7 +369,7 @@ impl<'a> VM<'a> {
|
|||||||
} else {
|
} else {
|
||||||
list.len()
|
list.len()
|
||||||
};
|
};
|
||||||
Ok(Value::NumberList(Box::new(list[start..end].to_vec())))
|
Ok(Value::NumberList(Rc::new(list[start..end].to_vec())))
|
||||||
}
|
}
|
||||||
_ => Err(VMError::RuntimeError("slice() requires a number index".to_string())),
|
_ => Err(VMError::RuntimeError("slice() requires a number index".to_string())),
|
||||||
}
|
}
|
||||||
@@ -376,12 +377,12 @@ impl<'a> VM<'a> {
|
|||||||
"reverse" => {
|
"reverse" => {
|
||||||
let mut reversed = list.to_vec();
|
let mut reversed = list.to_vec();
|
||||||
reversed.reverse();
|
reversed.reverse();
|
||||||
Ok(Value::NumberList(Box::new(reversed)))
|
Ok(Value::NumberList(Rc::new(reversed)))
|
||||||
}
|
}
|
||||||
"sort" => {
|
"sort" => {
|
||||||
let mut sorted = list.to_vec();
|
let mut sorted = list.to_vec();
|
||||||
sorted.sort();
|
sorted.sort();
|
||||||
Ok(Value::NumberList(Box::new(sorted)))
|
Ok(Value::NumberList(Rc::new(sorted)))
|
||||||
}
|
}
|
||||||
"sum" => {
|
"sum" => {
|
||||||
let sum: Decimal = list.iter().sum();
|
let sum: Decimal = list.iter().sum();
|
||||||
@@ -426,12 +427,12 @@ impl<'a> VM<'a> {
|
|||||||
match method {
|
match method {
|
||||||
"keys" => {
|
"keys" => {
|
||||||
let keys: Vec<SmolStr> = map.keys().cloned().collect();
|
let keys: Vec<SmolStr> = map.keys().cloned().collect();
|
||||||
Ok(Value::StringList(Box::new(keys)))
|
Ok(Value::StringList(Rc::new(keys)))
|
||||||
}
|
}
|
||||||
"values" => {
|
"values" => {
|
||||||
let vals: Vec<Value> = map.values().cloned().collect();
|
let vals: Vec<Value> = map.values().cloned().collect();
|
||||||
if vals.is_empty() {
|
if vals.is_empty() {
|
||||||
Ok(Value::StringList(Box::new(Vec::new())))
|
Ok(Value::StringList(Rc::new(Vec::new())))
|
||||||
} else if vals.iter().all(|v| matches!(v, Value::String(_))) {
|
} else if vals.iter().all(|v| matches!(v, Value::String(_))) {
|
||||||
let strings: Vec<SmolStr> = vals
|
let strings: Vec<SmolStr> = vals
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -440,7 +441,7 @@ impl<'a> VM<'a> {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
Ok(Value::StringList(Box::new(strings)))
|
Ok(Value::StringList(Rc::new(strings)))
|
||||||
} else if vals.iter().all(|v| matches!(v, Value::Number(_))) {
|
} else if vals.iter().all(|v| matches!(v, Value::Number(_))) {
|
||||||
let numbers: Vec<Decimal> = vals
|
let numbers: Vec<Decimal> = vals
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -449,7 +450,7 @@ impl<'a> VM<'a> {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
Ok(Value::NumberList(Box::new(numbers)))
|
Ok(Value::NumberList(Rc::new(numbers)))
|
||||||
} else {
|
} else {
|
||||||
Err(VMError::RuntimeError(
|
Err(VMError::RuntimeError(
|
||||||
"values() only works when all values are the same type (String or Number)".to_string(),
|
"values() only works when all values are the same type (String or Number)".to_string(),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::{ast::value::Value, bytecode::BytecodeReader, opcodes::OpCodeByte};
|
use crate::{ast::value::Value, bytecode::BytecodeReader, opcodes::OpCodeByte};
|
||||||
|
use std::rc::Rc;
|
||||||
use micromap::Map;
|
use micromap::Map;
|
||||||
use rust_decimal::{Decimal, MathematicalOps};
|
use rust_decimal::{Decimal, MathematicalOps};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
@@ -704,7 +705,7 @@ impl<'a> VM<'a> {
|
|||||||
let value = self.registers[val].clone();
|
let value = self.registers[val].clone();
|
||||||
match &mut self.registers[obj] {
|
match &mut self.registers[obj] {
|
||||||
Value::Object(map) => {
|
Value::Object(map) => {
|
||||||
map.insert(SmolStr::from(prop), value);
|
Rc::make_mut(map).insert(SmolStr::from(prop), value);
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
return Err(VMError::RuntimeError(format!(
|
return Err(VMError::RuntimeError(format!(
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use indexmap::IndexMap;
|
|||||||
use rust_decimal::Decimal;
|
use rust_decimal::Decimal;
|
||||||
use smol_str::SmolStr;
|
use smol_str::SmolStr;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
@@ -55,7 +56,7 @@ fn value_def_to_value(def: &ValueDef) -> Value {
|
|||||||
};
|
};
|
||||||
map.insert(SmolStr::from(k.as_str()), val);
|
map.insert(SmolStr::from(k.as_str()), val);
|
||||||
}
|
}
|
||||||
Value::Object(Box::new(map))
|
Value::Object(Rc::new(map))
|
||||||
}
|
}
|
||||||
let obj = def.value.as_ref().unwrap().as_object().unwrap();
|
let obj = def.value.as_ref().unwrap().as_object().unwrap();
|
||||||
json_obj_to_value(obj)
|
json_obj_to_value(obj)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use indexmap::IndexMap;
|
|||||||
use rust_decimal::prelude::ToPrimitive;
|
use rust_decimal::prelude::ToPrimitive;
|
||||||
use rust_decimal_macros::dec;
|
use rust_decimal_macros::dec;
|
||||||
use smol_str::SmolStr;
|
use smol_str::SmolStr;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
/// Helper to run code and get the value of "result" variable
|
/// Helper to run code and get the value of "result" variable
|
||||||
fn run_and_get_result(code: &str) -> Value {
|
fn run_and_get_result(code: &str) -> Value {
|
||||||
@@ -628,7 +629,7 @@ fn test_numberlist_contains() {
|
|||||||
let mut compiler = Compiler::new();
|
let mut compiler = Compiler::new();
|
||||||
let bytecode = compiler.compile(ast).expect("compile");
|
let bytecode = compiler.compile(ast).expect("compile");
|
||||||
let mut vm = VM::new(&bytecode);
|
let mut vm = VM::new(&bytecode);
|
||||||
vm.set_global("nums", Value::NumberList(Box::new(vec![dec!(1), dec!(2), dec!(3), dec!(4)])));
|
vm.set_global("nums", Value::NumberList(Rc::new(vec![dec!(1), dec!(2), dec!(3), dec!(4)])));
|
||||||
vm.execute().expect("execute");
|
vm.execute().expect("execute");
|
||||||
assert_eq!(vm.get_global("result").unwrap(), &Value::Boolean(true));
|
assert_eq!(vm.get_global("result").unwrap(), &Value::Boolean(true));
|
||||||
}
|
}
|
||||||
@@ -639,7 +640,7 @@ fn test_numberlist_indexof() {
|
|||||||
let mut compiler = Compiler::new();
|
let mut compiler = Compiler::new();
|
||||||
let bytecode = compiler.compile(ast).expect("compile");
|
let bytecode = compiler.compile(ast).expect("compile");
|
||||||
let mut vm = VM::new(&bytecode);
|
let mut vm = VM::new(&bytecode);
|
||||||
vm.set_global("nums", Value::NumberList(Box::new(vec![dec!(1), dec!(2), dec!(3)])));
|
vm.set_global("nums", Value::NumberList(Rc::new(vec![dec!(1), dec!(2), dec!(3)])));
|
||||||
vm.execute().expect("execute");
|
vm.execute().expect("execute");
|
||||||
assert_eq!(vm.get_global("result").unwrap(), &Value::Number(dec!(2)));
|
assert_eq!(vm.get_global("result").unwrap(), &Value::Number(dec!(2)));
|
||||||
}
|
}
|
||||||
@@ -650,7 +651,7 @@ fn test_numberlist_slice() {
|
|||||||
let mut compiler = Compiler::new();
|
let mut compiler = Compiler::new();
|
||||||
let bytecode = compiler.compile(ast).expect("compile");
|
let bytecode = compiler.compile(ast).expect("compile");
|
||||||
let mut vm = VM::new(&bytecode);
|
let mut vm = VM::new(&bytecode);
|
||||||
vm.set_global("nums", Value::NumberList(Box::new(vec![dec!(10), dec!(20), dec!(30), dec!(40)])));
|
vm.set_global("nums", Value::NumberList(Rc::new(vec![dec!(10), dec!(20), dec!(30), dec!(40)])));
|
||||||
vm.execute().expect("execute");
|
vm.execute().expect("execute");
|
||||||
// slice(1,3) = [20, 30], sum = 50
|
// slice(1,3) = [20, 30], sum = 50
|
||||||
assert_eq!(vm.get_global("result").unwrap(), &Value::Number(dec!(50)));
|
assert_eq!(vm.get_global("result").unwrap(), &Value::Number(dec!(50)));
|
||||||
@@ -662,7 +663,7 @@ fn test_numberlist_reverse() {
|
|||||||
let mut compiler = Compiler::new();
|
let mut compiler = Compiler::new();
|
||||||
let bytecode = compiler.compile(ast).expect("compile");
|
let bytecode = compiler.compile(ast).expect("compile");
|
||||||
let mut vm = VM::new(&bytecode);
|
let mut vm = VM::new(&bytecode);
|
||||||
vm.set_global("nums", Value::NumberList(Box::new(vec![dec!(1), dec!(2), dec!(3)])));
|
vm.set_global("nums", Value::NumberList(Rc::new(vec![dec!(1), dec!(2), dec!(3)])));
|
||||||
vm.execute().expect("execute");
|
vm.execute().expect("execute");
|
||||||
assert_eq!(vm.get_global("result").unwrap(), &Value::Number(dec!(3)));
|
assert_eq!(vm.get_global("result").unwrap(), &Value::Number(dec!(3)));
|
||||||
}
|
}
|
||||||
@@ -673,7 +674,7 @@ fn test_numberlist_sort() {
|
|||||||
let mut compiler = Compiler::new();
|
let mut compiler = Compiler::new();
|
||||||
let bytecode = compiler.compile(ast).expect("compile");
|
let bytecode = compiler.compile(ast).expect("compile");
|
||||||
let mut vm = VM::new(&bytecode);
|
let mut vm = VM::new(&bytecode);
|
||||||
vm.set_global("nums", Value::NumberList(Box::new(vec![dec!(30), dec!(10), dec!(20)])));
|
vm.set_global("nums", Value::NumberList(Rc::new(vec![dec!(30), dec!(10), dec!(20)])));
|
||||||
vm.execute().expect("execute");
|
vm.execute().expect("execute");
|
||||||
assert_eq!(vm.get_global("result").unwrap(), &Value::Number(dec!(10)));
|
assert_eq!(vm.get_global("result").unwrap(), &Value::Number(dec!(10)));
|
||||||
}
|
}
|
||||||
@@ -684,7 +685,7 @@ fn test_numberlist_isempty() {
|
|||||||
let mut compiler = Compiler::new();
|
let mut compiler = Compiler::new();
|
||||||
let bytecode = compiler.compile(ast).expect("compile");
|
let bytecode = compiler.compile(ast).expect("compile");
|
||||||
let mut vm = VM::new(&bytecode);
|
let mut vm = VM::new(&bytecode);
|
||||||
vm.set_global("nums", Value::NumberList(Box::new(vec![])));
|
vm.set_global("nums", Value::NumberList(Rc::new(vec![])));
|
||||||
vm.execute().expect("execute");
|
vm.execute().expect("execute");
|
||||||
assert_eq!(vm.get_global("result").unwrap(), &Value::Boolean(true));
|
assert_eq!(vm.get_global("result").unwrap(), &Value::Boolean(true));
|
||||||
}
|
}
|
||||||
@@ -1028,7 +1029,7 @@ fn make_object(entries: Vec<(&str, Value)>) -> Value {
|
|||||||
for (k, v) in entries {
|
for (k, v) in entries {
|
||||||
map.insert(SmolStr::new(k), v);
|
map.insert(SmolStr::new(k), v);
|
||||||
}
|
}
|
||||||
Value::Object(Box::new(map))
|
Value::Object(Rc::new(map))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -1113,7 +1114,7 @@ fn test_object_method_keys() {
|
|||||||
let result = run_expr_with_globals("person.keys()", vec![("person", obj)]);
|
let result = run_expr_with_globals("person.keys()", vec![("person", obj)]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
Value::StringList(Box::new(vec![SmolStr::new("name"), SmolStr::new("age")]))
|
Value::StringList(Rc::new(vec![SmolStr::new("name"), SmolStr::new("age")]))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1177,7 +1178,7 @@ fn test_object_method_values_strings() {
|
|||||||
let result = run_expr_with_globals("obj.values()", vec![("obj", obj)]);
|
let result = run_expr_with_globals("obj.values()", vec![("obj", obj)]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
Value::StringList(Box::new(vec![SmolStr::new("x"), SmolStr::new("y")]))
|
Value::StringList(Rc::new(vec![SmolStr::new("x"), SmolStr::new("y")]))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1188,7 +1189,7 @@ fn test_object_method_values_numbers() {
|
|||||||
("b", Value::Number(dec!(2))),
|
("b", Value::Number(dec!(2))),
|
||||||
]);
|
]);
|
||||||
let result = run_expr_with_globals("obj.values()", vec![("obj", obj)]);
|
let result = run_expr_with_globals("obj.values()", vec![("obj", obj)]);
|
||||||
assert_eq!(result, Value::NumberList(Box::new(vec![dec!(1), dec!(2)])));
|
assert_eq!(result, Value::NumberList(Rc::new(vec![dec!(1), dec!(2)])));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user