builtins.rs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. use crate::ast::*;
  2. use crate::interp::*;
  3. use anyhow::{bail, Error};
  4. /// The list of builtins provided at startup.
  5. pub fn builtins() -> Vec<BuiltinFunc> {
  6. vec![
  7. BuiltinFunc {
  8. name: "rep",
  9. callback: Box::new(|state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  10. if let [rep, expr] = exprs {
  11. let mut buf = String::new();
  12. let num = state.eval(*rep, env)?.as_num(&state.ast.borrow())?;
  13. for _ in 0..num {
  14. buf.push_str(
  15. &state
  16. .eval(*expr, env)?
  17. .as_str(&state.ast.borrow())?
  18. .to_string(),
  19. );
  20. }
  21. Ok(Value::Lit(Literal::Str(buf)))
  22. } else {
  23. bail!("`rep`: expected two arguments, got {}", exprs.len())
  24. }
  25. }),
  26. },
  27. BuiltinFunc {
  28. name: "str/upper",
  29. callback: Box::new(|state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  30. if let [expr] = exprs {
  31. let s = state.eval(*expr, env)?;
  32. Ok(Value::Lit(Literal::Str(
  33. s.as_str(&state.ast.borrow())?.to_uppercase(),
  34. )))
  35. } else {
  36. bail!("`str/capitalize`: expected 1 argument1, got {}", exprs.len());
  37. }
  38. }),
  39. },
  40. BuiltinFunc {
  41. name: "str/capitalize",
  42. callback: Box::new(|state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  43. if let [expr] = exprs {
  44. let s = state.eval(*expr, env)?;
  45. Ok(Value::Lit(Literal::Str(titlecase::titlecase(
  46. s.as_str(&state.ast.borrow())?,
  47. ))))
  48. } else {
  49. bail!("`str/capitalize`: expected 1 argument1, got {}", exprs.len());
  50. }
  51. }),
  52. },
  53. BuiltinFunc {
  54. name: "str/lower",
  55. callback: Box::new(|state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  56. if let [expr] = exprs {
  57. let s = state.eval(*expr, env)?;
  58. Ok(Value::Lit(Literal::Str(
  59. s.as_str(&state.ast.borrow())?.to_lowercase(),
  60. )))
  61. } else {
  62. bail!("`str/lower`: expected 1 argument1, got {}", exprs.len());
  63. }
  64. }),
  65. },
  66. BuiltinFunc {
  67. name: "sub",
  68. callback: Box::new(|state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  69. if let [x, y] = exprs {
  70. let x = state.eval(*x, env)?.as_num(&state.ast.borrow())?;
  71. let y = state.eval(*y, env)?.as_num(&state.ast.borrow())?;
  72. Ok(Value::Lit(Literal::Num(x - y)))
  73. } else {
  74. bail!("`sub`: expected 2 arguments, got {}", exprs.len());
  75. }
  76. }),
  77. },
  78. BuiltinFunc {
  79. name: "tuple/len",
  80. callback: Box::new(|state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  81. if let [expr] = exprs {
  82. let tup = state.eval(*expr, env)?;
  83. Ok(Value::Lit(Literal::Num(tup.as_tup(&state.ast.borrow())?.len() as i64)))
  84. } else {
  85. bail!("`tuple/len`: expected 1 argument, got {}", exprs.len())
  86. }
  87. }),
  88. },
  89. BuiltinFunc {
  90. name: "tuple/concat",
  91. callback: Box::new(|state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  92. if let [expr] = exprs {
  93. let val = state.eval(*expr, env)?;
  94. let tup = val.as_tup(&state.ast.borrow())?;
  95. let mut contents = Vec::new();
  96. for elem in tup {
  97. for th in state.hnf(elem)?.as_tup(&state.ast.borrow())? {
  98. contents.push(th.clone());
  99. }
  100. }
  101. Ok(Value::Tup(contents))
  102. } else {
  103. bail!("tuple/concat: expected 1 argument, got {}", exprs.len());
  104. }
  105. }),
  106. },
  107. BuiltinFunc {
  108. name: "tuple/index",
  109. callback: Box::new(|state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  110. if let [tup, idx] = exprs {
  111. let tup = state.eval(*tup, env)?;
  112. let idx = state.eval(*idx, env)?;
  113. state.hnf(
  114. &tup.as_tup(&state.ast.borrow())?
  115. [idx.as_num(&state.ast.borrow())? as usize],
  116. )
  117. } else {
  118. bail!("`tuple/index`: expected 2 arguments, got {}", exprs.len());
  119. }
  120. }),
  121. },
  122. BuiltinFunc {
  123. name: "tuple/replace",
  124. callback: Box::new(|state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  125. if let [tup, idx, new] = exprs {
  126. let tup_val = state.eval(*tup, env)?;
  127. let tup = tup_val.as_tup(&state.ast.borrow())?;
  128. let idx = state.eval(*idx, env)?.as_num(&state.ast.borrow())?;
  129. let mut modified = Vec::with_capacity(tup.len());
  130. for i in 0..idx {
  131. modified.push(tup[i as usize].clone());
  132. }
  133. modified.push(Thunk::Expr(*new, env.clone()));
  134. for i in (idx + 1)..(tup.len() as i64) {
  135. modified.push(tup[i as usize].clone());
  136. }
  137. Ok(Value::Tup(modified))
  138. } else {
  139. bail!("`tuple/replace`: expected 3 arguments, got {}", exprs.len());
  140. }
  141. }),
  142. },
  143. BuiltinFunc {
  144. name: "tuple/fold",
  145. callback: Box::new(|state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  146. if let [func, init, tup] = exprs {
  147. let func = state.eval(*func, env)?;
  148. let tup = state.eval(*tup, env)?;
  149. let mut result = Thunk::Expr(*init, env.clone());
  150. for t in tup.as_tup(&state.ast.borrow())? {
  151. result = Thunk::Value(
  152. state.eval_closure(
  153. func.as_closure(&state.ast.borrow())?,
  154. vec![result, t.clone()],
  155. )?);
  156. }
  157. state.hnf(&result)
  158. } else {
  159. bail!("`tuple/fold`: expected 3 arguments, got {}", exprs.len());
  160. }
  161. }),
  162. },
  163. ]
  164. }