builtins.rs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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(
  10. |state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  11. if let [rep, expr] = exprs {
  12. let mut buf = String::new();
  13. let num = state.eval(*rep, env)?.as_num(&state.ast.borrow())?;
  14. for _ in 0..num {
  15. buf.push_str(state.eval(*expr, env)?.as_str(&state.ast.borrow())?);
  16. }
  17. Ok(Value::Lit(Literal::Str(buf)))
  18. } else {
  19. bail!("`rep`: expected two arguments, got {}", exprs.len())
  20. }
  21. },
  22. ),
  23. },
  24. BuiltinFunc {
  25. name: "str/upper",
  26. callback: Box::new(
  27. |state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  28. if let [expr] = exprs {
  29. let s = state.eval(*expr, env)?;
  30. Ok(Value::Lit(Literal::Str(
  31. s.as_str(&state.ast.borrow())?.to_uppercase(),
  32. )))
  33. } else {
  34. bail!(
  35. "`str/capitalize`: expected 1 argument1, got {}",
  36. exprs.len()
  37. );
  38. }
  39. },
  40. ),
  41. },
  42. BuiltinFunc {
  43. name: "str/capitalize",
  44. callback: Box::new(
  45. |state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  46. if let [expr] = exprs {
  47. let s = state.eval(*expr, env)?;
  48. Ok(Value::Lit(Literal::Str(titlecase::titlecase(
  49. s.as_str(&state.ast.borrow())?,
  50. ))))
  51. } else {
  52. bail!(
  53. "`str/capitalize`: expected 1 argument1, got {}",
  54. exprs.len()
  55. );
  56. }
  57. },
  58. ),
  59. },
  60. BuiltinFunc {
  61. name: "str/lower",
  62. callback: Box::new(
  63. |state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  64. if let [expr] = exprs {
  65. let s = state.eval(*expr, env)?;
  66. Ok(Value::Lit(Literal::Str(
  67. s.as_str(&state.ast.borrow())?.to_lowercase(),
  68. )))
  69. } else {
  70. bail!("`str/lower`: expected 1 argument1, got {}", exprs.len());
  71. }
  72. },
  73. ),
  74. },
  75. BuiltinFunc {
  76. name: "add",
  77. callback: Box::new(
  78. |state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  79. if let [x, y] = exprs {
  80. let x = state.eval(*x, env)?.as_num(&state.ast.borrow())?;
  81. let y = state.eval(*y, env)?.as_num(&state.ast.borrow())?;
  82. Ok(Value::Lit(Literal::Num(x + y)))
  83. } else {
  84. bail!("`add`: expected 2 arguments, got {}", exprs.len());
  85. }
  86. },
  87. ),
  88. },
  89. BuiltinFunc {
  90. name: "sub",
  91. callback: Box::new(
  92. |state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  93. if let [x, y] = exprs {
  94. let x = state.eval(*x, env)?.as_num(&state.ast.borrow())?;
  95. let y = state.eval(*y, env)?.as_num(&state.ast.borrow())?;
  96. Ok(Value::Lit(Literal::Num(x - y)))
  97. } else {
  98. bail!("`sub`: expected 2 arguments, got {}", exprs.len());
  99. }
  100. },
  101. ),
  102. },
  103. BuiltinFunc {
  104. name: "mul",
  105. callback: Box::new(
  106. |state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  107. if let [x, y] = exprs {
  108. let x = state.eval(*x, env)?.as_num(&state.ast.borrow())?;
  109. let y = state.eval(*y, env)?.as_num(&state.ast.borrow())?;
  110. Ok(Value::Lit(Literal::Num(x * y)))
  111. } else {
  112. bail!("`mul`: expected 2 arguments, got {}", exprs.len());
  113. }
  114. },
  115. ),
  116. },
  117. BuiltinFunc {
  118. name: "tuple/len",
  119. callback: Box::new(
  120. |state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  121. if let [expr] = exprs {
  122. let tup = state.eval(*expr, env)?;
  123. Ok(Value::Lit(Literal::Num(
  124. tup.as_tup(&state.ast.borrow())?.len() as i64,
  125. )))
  126. } else {
  127. bail!("`tuple/len`: expected 1 argument, got {}", exprs.len())
  128. }
  129. },
  130. ),
  131. },
  132. BuiltinFunc {
  133. name: "tuple/concat",
  134. callback: Box::new(
  135. |state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  136. if let [expr] = exprs {
  137. let val = state.eval(*expr, env)?;
  138. let tup = val.as_tup(&state.ast.borrow())?;
  139. let mut contents = Vec::new();
  140. for elem in tup {
  141. for th in state.hnf(elem)?.as_tup(&state.ast.borrow())? {
  142. contents.push(th.clone());
  143. }
  144. }
  145. Ok(Value::Tup(contents))
  146. } else {
  147. bail!("tuple/concat: expected 1 argument, got {}", exprs.len());
  148. }
  149. },
  150. ),
  151. },
  152. BuiltinFunc {
  153. name: "tuple/index",
  154. callback: Box::new(
  155. |state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  156. if let [tup, idx] = exprs {
  157. let tup = state.eval(*tup, env)?;
  158. let idx = state.eval(*idx, env)?;
  159. state.hnf(
  160. &tup.as_tup(&state.ast.borrow())?
  161. [idx.as_num(&state.ast.borrow())? as usize],
  162. )
  163. } else {
  164. bail!("`tuple/index`: expected 2 arguments, got {}", exprs.len());
  165. }
  166. },
  167. ),
  168. },
  169. BuiltinFunc {
  170. name: "tuple/replace",
  171. callback: Box::new(
  172. |state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  173. if let [tup, idx, new] = exprs {
  174. let tup_val = state.eval(*tup, env)?;
  175. let tup = tup_val.as_tup(&state.ast.borrow())?;
  176. let idx = state.eval(*idx, env)?.as_num(&state.ast.borrow())?;
  177. let mut modified = Vec::with_capacity(tup.len());
  178. for i in 0..idx {
  179. modified.push(tup[i as usize].clone());
  180. }
  181. modified.push(Thunk::Expr(*new, env.clone()));
  182. for i in (idx + 1)..(tup.len() as i64) {
  183. modified.push(tup[i as usize].clone());
  184. }
  185. Ok(Value::Tup(modified))
  186. } else {
  187. bail!("`tuple/replace`: expected 3 arguments, got {}", exprs.len());
  188. }
  189. },
  190. ),
  191. },
  192. BuiltinFunc {
  193. name: "tuple/fold",
  194. callback: Box::new(
  195. |state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  196. if let [func, init, tup] = exprs {
  197. let func = state.eval(*func, env)?;
  198. let tup = state.eval(*tup, env)?;
  199. let mut result = Thunk::Expr(*init, env.clone());
  200. for t in tup.as_tup(&state.ast.borrow())? {
  201. result = Thunk::Value(state.eval_closure(
  202. func.as_closure(&state.ast.borrow())?,
  203. vec![result, t.clone()],
  204. )?);
  205. }
  206. state.hnf(&result)
  207. } else {
  208. bail!("`tuple/fold`: expected 3 arguments, got {}", exprs.len());
  209. }
  210. },
  211. ),
  212. },
  213. BuiltinFunc {
  214. name: "tuple/map",
  215. callback: Box::new(
  216. |state: &State, exprs: &[ExprRef], env: &Env| -> Result<Value, Error> {
  217. if let [func, tup] = exprs {
  218. let func = state.eval(*func, env)?;
  219. let tup = state.eval(*tup, env)?;
  220. let mut new_tup = Vec::new();
  221. let closure = func.as_closure(&state.ast.borrow())?;
  222. for t in tup.as_tup(&state.ast.borrow())? {
  223. new_tup
  224. .push(Thunk::Value(state.eval_closure(closure, vec![t.clone()])?));
  225. }
  226. Ok(Value::Tup(new_tup))
  227. } else {
  228. bail!("`tuple/map`: expected 2 arguments, got {}", exprs.len());
  229. }
  230. },
  231. ),
  232. },
  233. ]
  234. }