From 7df53f6975304edb35e7bdb412dbff021da69a24 Mon Sep 17 00:00:00 2001 From: upstream Date: Wed, 2 Sep 2026 10:25:31 +0200 Subject: [PATCH] Upstream sharkdp/numbat state of the touched files before fa2c3ddcfe --- examples/tests/strings.nbt | 28 ++++++++++++++ numbat/src/ffi/strings.rs | 75 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 examples/tests/strings.nbt create mode 100644 numbat/src/ffi/strings.rs diff --git a/examples/tests/strings.nbt b/examples/tests/strings.nbt new file mode 100644 index 0000000..2678dee --- /dev/null +++ b/examples/tests/strings.nbt @@ -0,0 +1,28 @@ +assert_eq(str_length(""), 0) +assert_eq(str_length("foo"), 3) + +assert_eq(str_slice(0, 5, "hello world"), "hello") +assert_eq(str_slice(6, 11, "hello world"), "world") +assert_eq(str_slice(0, 0, "hello world"), "") +assert_eq(str_slice(0, 100, "hello world"), "") + +assert_eq(chr(65), "A") +assert_eq(chr(97), "a") +assert_eq(chr(0x2764), "❤") + +assert_eq(ord("A"), 65) +assert_eq(ord("a"), 97) +assert_eq(ord("❤"), 0x2764) + +assert_eq(str_append("foo", "bar"), "foobar") +assert_eq(str_prepend("bar", "foo"), "foobar") + +assert(str_contains("hello", "hello world")) +assert(str_contains("world", "hello world")) +assert_eq(str_contains("HELLO", "hello world"), false) + +assert_eq(str_replace("hello", "HEY", "hello world"), "HEY world") +assert_eq(str_replace("x", "yY", "xxx"), "yYyYyY") +assert_eq(str_replace(" ", " ", "a b"), "a b") + +assert_eq(str_repeat(3, "xy"), "xyxyxy") diff --git a/numbat/src/ffi/strings.rs b/numbat/src/ffi/strings.rs new file mode 100644 index 0000000..a810080 --- /dev/null +++ b/numbat/src/ffi/strings.rs @@ -0,0 +1,75 @@ +use super::Args; +use super::FfiContext; +use super::Result; +use super::macros::*; +use crate::interpreter::RuntimeErrorKind; +use crate::quantity::Quantity; +use crate::typechecker::type_scheme::TypeScheme; +use crate::value::Value; + +pub fn str_length( + _ctx: &mut FfiContext, + mut args: Args, + _return_type: &TypeScheme, +) -> Result> { + let len = string_arg!(args).len(); + return_scalar!(len as f64) +} + +pub fn lowercase( + _ctx: &mut FfiContext, + mut args: Args, + _return_type: &TypeScheme, +) -> Result> { + return_string!(owned = string_arg!(args).to_lowercase()) +} + +pub fn uppercase( + _ctx: &mut FfiContext, + mut args: Args, + _return_type: &TypeScheme, +) -> Result> { + return_string!(owned = string_arg!(args).to_uppercase()) +} + +pub fn str_slice( + _ctx: &mut FfiContext, + mut args: Args, + _return_type: &TypeScheme, +) -> Result> { + let start = quantity_arg!(args).unsafe_value().to_f64() as usize; + let end = quantity_arg!(args).unsafe_value().to_f64() as usize; + let input = string_arg!(args); + + let output = input.get(start..end).unwrap_or_default(); + + return_string!(borrowed = output) +} + +pub fn chr( + _ctx: &mut FfiContext, + mut args: Args, + _return_type: &TypeScheme, +) -> Result> { + let idx = quantity_arg!(args).unsafe_value().to_f64() as u32; + + let output = char::from_u32(idx).unwrap_or('�'); + + return_string!(from = &output) +} + +pub fn ord( + _ctx: &mut FfiContext, + mut args: Args, + _return_type: &TypeScheme, +) -> Result> { + let input = string_arg!(args); + + if input.is_empty() { + return Err(Box::new(RuntimeErrorKind::EmptyList)); + } + + let output = input.chars().next().unwrap() as u32; + + return_scalar!(output as f64) +}