浏览代码

Add basic hex conversion

David Peter 1 年之前
父节点
当前提交
ac86c5563d

+ 2 - 0
book/src/list-functions.md

@@ -119,4 +119,6 @@ fn str_append(a: String, b: String) -> String
 fn str_contains(haystack: String, needle: String) -> Bool
 fn str_replace(s: String, pattern: String, replacement: String) -> String
 fn str_repeat(a: String, n: Scalar) -> String
+fn chr(n: Scalar) -> String
+fn hex(n: Scalar) -> String
 ```

+ 8 - 0
examples/prelude_tests.nbt

@@ -72,3 +72,11 @@ assert(str_replace("hello world", "hello", "HEY") == "HEY world")
 assert(str_replace("xxx", "x", "yY") == "yYyYyY")
 
 assert(str_repeat("xy", 3) == "xyxyxy")
+
+assert(hex(0x0) == "0x0")
+assert(hex(0x1) == "0x1")
+assert(hex(0x9) == "0x9")
+assert(hex(0xa) == "0xa")
+assert(hex(0xf) == "0xf")
+assert(hex(0xabc1234567890) == "0xabc1234567890")
+assert(hex(-0xc0ffee) == "-0xc0ffee")

+ 5 - 0
numbat/modules/core/functions.nbt

@@ -0,0 +1,5 @@
+fn abs<T>(x: T) -> T
+fn round<T>(x: T) -> T
+fn floor<T>(x: T) -> T
+fn ceil<T>(x: T) -> T
+fn mod<T>(a: T, b: T) -> T

+ 13 - 0
numbat/modules/core/strings.nbt

@@ -1,9 +1,12 @@
 use core::scalar
+use core::functions
 
 fn str_length(s: String) -> Scalar
 
 fn str_slice(s: String, start: Scalar, end: Scalar) -> String
 
+fn chr(n: Scalar) -> String
+
 fn str_append(a: String, b: String) -> String = "{a}{b}"
 
 fn str_contains(haystack: String, needle: String) -> Bool =
@@ -26,3 +29,13 @@ fn str_repeat(a: String, n: Scalar) -> String =
   if n > 0
     then str_append(a, str_repeat(a, n - 1))
     else ""
+
+fn hex_digit(x: Scalar) -> String =
+    if mod(x, 16) < 10 then chr(48 + mod(x, 16)) else chr(97 + mod(x, 16) - 10)
+
+fn hex(x: Scalar) -> String =
+    if x < 0
+      then "-{hex(-x)}"
+      else if floor(x / 16) == 0
+        then str_append("0x", hex_digit(x))
+        else str_append(hex(floor(x / 16)), hex_digit(x))

+ 0 - 5
numbat/modules/math/functions.nbt

@@ -3,11 +3,6 @@ use math::constants
 
 ## Basics
 
-fn abs<T>(x: T) -> T
-fn round<T>(x: T) -> T
-fn floor<T>(x: T) -> T
-fn ceil<T>(x: T) -> T
-fn mod<T>(a: T, b: T) -> T
 fn sqrt<D>(x: D^2) -> D = x^(1/2)
 fn sqr<D>(x: D) -> D^2 = x^2
 

+ 1 - 0
numbat/modules/prelude.nbt

@@ -1,6 +1,7 @@
 use core::scalar
 use core::quantities
 use core::dimensions
+use core::functions
 use core::strings
 use core::error
 

+ 18 - 0
numbat/src/ffi.rs

@@ -323,6 +323,14 @@ pub(crate) fn functions() -> &'static HashMap<String, ForeignFunction> {
                 callable: Callable::Function(Box::new(str_slice)),
             },
         );
+        m.insert(
+            "chr".to_string(),
+            ForeignFunction {
+                name: "chr".into(),
+                arity: 1..=1,
+                callable: Callable::Function(Box::new(chr)),
+            },
+        );
 
         m
     })
@@ -722,3 +730,13 @@ fn str_slice(args: &[Value]) -> Result<Value> {
 
     Ok(Value::String(output.into()))
 }
+
+fn chr(args: &[Value]) -> Result<Value> {
+    assert!(args.len() == 1);
+
+    let idx = args[0].unsafe_as_quantity().unsafe_value().to_f64() as u32;
+
+    let output = char::from_u32(idx).unwrap_or('�');
+
+    Ok(Value::String(output.to_string()))
+}