瀏覽代碼

add some more stdlib methods

Getty Ritter 2 年之前
父節點
當前提交
ab7378a81c
共有 1 個文件被更改,包括 35 次插入5 次删除
  1. 35 5
      src/interp.rs

+ 35 - 5
src/interp.rs

@@ -23,6 +23,13 @@ impl Value {
         }
     }
 
+    fn as_str(&self) -> Result<&str, Error> {
+        match self {
+            Value::Lit(Literal::Str(s)) => Ok(s),
+            _ => self.with_str(|s| bail!("Expected string, got {}", s)),
+        }
+    }
+
     fn with_str<U>(&self, f: impl Fn(&str) -> U) -> U {
         match self {
             Value::Lit(Literal::Str(s)) => f(&s),
@@ -79,15 +86,38 @@ const BUILTINS: &[BuiltinFunc] = &[
             if args.len() != 2 {
                 bail!("`rep`: expected two arguments, got {}", args.len())
             }
-            let num = match state.eval(&args[0])? {
-                Value::Lit(Literal::Num(n)) => n,
-                r => bail!("`rep`: expected first arg to be a number, but got {:?}", r),
-            };
-
+            let num = state.eval(&args[0])?.as_num()?;
             let rep = (0..num).map(|_| args[1].clone()).collect();
             state.eval(&Expr::Cat(rep))
         }
     },
+
+    BuiltinFunc {
+        name: "length",
+        callback: &|_state: &mut State, expr: &Expr| -> Result<Value, Error> {
+            let args = match expr {
+                Expr::Tup(tup) => tup,
+                _ => bail!("`length`: expected tuple"),
+            };
+            Ok(Value::Lit(Literal::Num(args.len() as i64)))
+        }
+    },
+
+    BuiltinFunc {
+        name: "to-upper",
+        callback: &|state: &mut State, expr: &Expr| -> Result<Value, Error> {
+            let s = state.eval(expr)?;
+            Ok(Value::Lit(Literal::Str(s.as_str()?.to_uppercase())))
+        }
+    },
+
+    BuiltinFunc {
+        name: "to-lower",
+        callback: &|state: &mut State, expr: &Expr| -> Result<Value, Error> {
+            let s = state.eval(expr)?;
+            Ok(Value::Lit(Literal::Str(s.as_str()?.to_lowercase())))
+        }
+    },
 ];
 
 impl fmt::Debug for BuiltinFunc {