lisp.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. #![allow(non_snake_case)]
  2. use std::rc::Rc;
  3. //use std::collections::HashMap;
  4. use fnv::FnvHashMap;
  5. use itertools::Itertools;
  6. #[macro_use]
  7. extern crate lazy_static;
  8. extern crate fnv;
  9. extern crate itertools;
  10. extern crate regex;
  11. #[macro_use]
  12. mod types;
  13. use crate::types::MalErr::{ErrMalVal, ErrString};
  14. use crate::types::MalVal::{Bool, Func, Hash, List, MalFunc, Nil, Str, Sym, Vector};
  15. use crate::types::{error, format_error, MalArgs, MalErr, MalRet, MalVal};
  16. mod env;
  17. mod printer;
  18. mod reader;
  19. use crate::env::{env_bind, env_find, env_get, env_new, env_set, env_sets, Env};
  20. #[macro_use]
  21. mod core;
  22. // zk circuit
  23. fn zkcircuit_load(val: &MalVal) -> MalRet {
  24. Ok(val.clone())
  25. }
  26. // read
  27. fn read(str: &str) -> MalRet {
  28. reader::read_str(str.to_string())
  29. }
  30. // eval
  31. fn qq_iter(elts: &MalArgs) -> MalVal {
  32. let mut acc = list![];
  33. for elt in elts.iter().rev() {
  34. if let List(v, _) = elt {
  35. if v.len() == 2 {
  36. if let Sym(ref s) = v[0] {
  37. if s == "splice-unquote" {
  38. acc = list![Sym("concat".to_string()), v[1].clone(), acc];
  39. continue;
  40. }
  41. }
  42. }
  43. }
  44. acc = list![Sym("cons".to_string()), quasiquote(&elt), acc];
  45. }
  46. return acc;
  47. }
  48. fn quasiquote(ast: &MalVal) -> MalVal {
  49. match ast {
  50. List(v, _) => {
  51. if v.len() == 2 {
  52. if let Sym(ref s) = v[0] {
  53. if s == "unquote" {
  54. return v[1].clone();
  55. }
  56. }
  57. }
  58. return qq_iter(&v);
  59. },
  60. Vector(v, _) => return list![Sym("vec".to_string()), qq_iter(&v)],
  61. Hash(_, _) | Sym(_)=> return list![Sym("quote".to_string()), ast.clone()],
  62. _ => ast.clone(),
  63. }
  64. }
  65. fn is_macro_call(ast: &MalVal, env: &Env) -> Option<(MalVal, MalArgs)> {
  66. match ast {
  67. List(v, _) => match v[0] {
  68. Sym(ref s) => match env_find(env, s) {
  69. Some(e) => match env_get(&e, &v[0]) {
  70. Ok(f @ MalFunc { is_macro: true, .. }) => Some((f, v[1..].to_vec())),
  71. _ => None,
  72. },
  73. _ => None,
  74. },
  75. _ => None,
  76. },
  77. _ => None,
  78. }
  79. }
  80. fn macroexpand(mut ast: MalVal, env: &Env) -> (bool, MalRet) {
  81. let mut was_expanded = false;
  82. while let Some((mf, args)) = is_macro_call(&ast, env) {
  83. //println!("macroexpand 1: {:?}", ast);
  84. ast = match mf.apply(args) {
  85. Err(e) => return (false, Err(e)),
  86. Ok(a) => a,
  87. };
  88. //println!("macroexpand 2: {:?}", ast);
  89. was_expanded = true;
  90. }
  91. ((was_expanded, Ok(ast)))
  92. }
  93. fn eval_ast(ast: &MalVal, env: &Env) -> MalRet {
  94. match ast {
  95. Sym(_) => Ok(env_get(&env, &ast)?),
  96. List(v, _) => {
  97. let mut lst: MalArgs = vec![];
  98. for a in v.iter() {
  99. lst.push(eval(a.clone(), env.clone())?)
  100. }
  101. Ok(list!(lst))
  102. }
  103. Vector(v, _) => {
  104. let mut lst: MalArgs = vec![];
  105. for a in v.iter() {
  106. lst.push(eval(a.clone(), env.clone())?)
  107. }
  108. Ok(vector!(lst))
  109. }
  110. Hash(hm, _) => {
  111. let mut new_hm: FnvHashMap<String, MalVal> = FnvHashMap::default();
  112. for (k, v) in hm.iter() {
  113. new_hm.insert(k.to_string(), eval(v.clone(), env.clone())?);
  114. }
  115. Ok(Hash(Rc::new(new_hm), Rc::new(Nil)))
  116. }
  117. _ => Ok(ast.clone()),
  118. }
  119. }
  120. fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
  121. let ret: MalRet;
  122. 'tco: loop {
  123. ret = match ast.clone() {
  124. List(l, _) => {
  125. if l.len() == 0 {
  126. return Ok(ast);
  127. }
  128. match macroexpand(ast.clone(), &env) {
  129. (true, Ok(new_ast)) => {
  130. ast = new_ast;
  131. continue 'tco;
  132. }
  133. (_, Err(e)) => return Err(e),
  134. _ => (),
  135. }
  136. if l.len() == 0 {
  137. return Ok(ast);
  138. }
  139. let a0 = &l[0];
  140. match a0 {
  141. Sym(ref a0sym) if a0sym == "def!" => {
  142. env_set(&env, l[1].clone(), eval(l[2].clone(), env.clone())?)
  143. }
  144. Sym(ref a0sym) if a0sym == "let*" => {
  145. env = env_new(Some(env.clone()));
  146. let (a1, a2) = (l[1].clone(), l[2].clone());
  147. match a1 {
  148. List(ref binds, _) | Vector(ref binds, _) => {
  149. for (b, e) in binds.iter().tuples() {
  150. match b {
  151. Sym(_) => {
  152. let _ = env_set(
  153. &env,
  154. b.clone(),
  155. eval(e.clone(), env.clone())?,
  156. );
  157. }
  158. _ => {
  159. return error("let* with non-Sym binding");
  160. }
  161. }
  162. }
  163. }
  164. _ => {
  165. return error("let* with non-List bindings");
  166. }
  167. };
  168. ast = a2;
  169. continue 'tco;
  170. }
  171. Sym(ref a0sym) if a0sym == "quote" => Ok(l[1].clone()),
  172. Sym(ref a0sym) if a0sym == "quasiquoteexpand" => Ok(quasiquote(&l[1])),
  173. Sym(ref a0sym) if a0sym == "quasiquote" => {
  174. ast = quasiquote(&l[1]);
  175. continue 'tco;
  176. }
  177. Sym(ref a0sym) if a0sym == "defmacro!" => {
  178. let (a1, a2) = (l[1].clone(), l[2].clone());
  179. let r = eval(a2, env.clone())?;
  180. match r {
  181. MalFunc {
  182. eval,
  183. ast,
  184. env,
  185. params,
  186. ..
  187. } => Ok(env_set(
  188. &env,
  189. a1.clone(),
  190. MalFunc {
  191. eval: eval,
  192. ast: ast.clone(),
  193. env: env.clone(),
  194. params: params.clone(),
  195. is_macro: true,
  196. meta: Rc::new(Nil),
  197. },
  198. )?),
  199. _ => error("set_macro on non-function"),
  200. }
  201. }
  202. Sym(ref a0sym) if a0sym == "macroexpand" => {
  203. match macroexpand(l[1].clone(), &env) {
  204. (_, Ok(new_ast)) => Ok(new_ast),
  205. (_, e) => return e,
  206. }
  207. }
  208. Sym(ref a0sym) if a0sym == "try*" => match eval(l[1].clone(), env.clone()) {
  209. Err(ref e) if l.len() >= 3 => {
  210. let exc = match e {
  211. ErrMalVal(mv) => mv.clone(),
  212. ErrString(s) => Str(s.to_string()),
  213. };
  214. match l[2].clone() {
  215. List(c, _) => {
  216. let catch_env = env_bind(
  217. Some(env.clone()),
  218. list!(vec![c[1].clone()]),
  219. vec![exc],
  220. )?;
  221. eval(c[2].clone(), catch_env)
  222. }
  223. _ => error("invalid catch block"),
  224. }
  225. }
  226. res => res,
  227. },
  228. Sym(ref a0sym) if a0sym == "do" => {
  229. match eval_ast(&list!(l[1..l.len() - 1].to_vec()), &env)? {
  230. List(_, _) => {
  231. ast = l.last().unwrap_or(&Nil).clone();
  232. continue 'tco;
  233. }
  234. _ => error("invalid do form"),
  235. }
  236. }
  237. Sym(ref a0sym) if a0sym == "if" => {
  238. let cond = eval(l[1].clone(), env.clone())?;
  239. match cond {
  240. Bool(false) | Nil if l.len() >= 4 => {
  241. ast = l[3].clone();
  242. continue 'tco;
  243. }
  244. Bool(false) | Nil => Ok(Nil),
  245. _ if l.len() >= 3 => {
  246. ast = l[2].clone();
  247. continue 'tco;
  248. }
  249. _ => Ok(Nil),
  250. }
  251. }
  252. Sym(ref a0sym) if a0sym == "fn*" => {
  253. let (a1, a2) = (l[1].clone(), l[2].clone());
  254. Ok(MalFunc {
  255. eval: eval,
  256. ast: Rc::new(a2),
  257. env: env,
  258. params: Rc::new(a1),
  259. is_macro: false,
  260. meta: Rc::new(Nil),
  261. })
  262. }
  263. Sym(ref a0sym) if a0sym == "eval" => {
  264. ast = eval(l[1].clone(), env.clone())?;
  265. while let Some(ref e) = env.clone().outer {
  266. env = e.clone();
  267. }
  268. continue 'tco;
  269. }
  270. _ => match eval_ast(&ast, &env)? {
  271. List(ref el, _) => {
  272. let ref f = el[0].clone();
  273. let args = el[1..].to_vec();
  274. match f {
  275. Func(_, _) => f.apply(args),
  276. MalFunc {
  277. ast: mast,
  278. env: menv,
  279. params,
  280. ..
  281. } => {
  282. let a = &**mast;
  283. let p = &**params;
  284. env = env_bind(Some(menv.clone()), p.clone(), args)?;
  285. ast = a.clone();
  286. continue 'tco;
  287. }
  288. _ => {
  289. Ok(Nil)
  290. //error("attempt to call non-function")
  291. },
  292. }
  293. }
  294. _ => error("expected a list"),
  295. },
  296. }
  297. }
  298. _ => eval_ast(&ast, &env),
  299. };
  300. break;
  301. } // end 'tco loop
  302. ret
  303. }
  304. // print
  305. fn print(ast: &MalVal) -> String {
  306. ast.pr_str(true)
  307. }
  308. fn rep(str: &str, env: &Env) -> Result<String, MalErr> {
  309. let ast = read(str)?;
  310. let exp = eval(ast, env.clone())?;
  311. Ok(print(&exp))
  312. }
  313. fn main() {
  314. let mut args = std::env::args();
  315. let arg1 = args.nth(1);
  316. // core.rs: defined using rust
  317. let repl_env = env_new(None);
  318. for (k, v) in core::ns() {
  319. env_sets(&repl_env, k, v);
  320. }
  321. env_sets(&repl_env, "*ARGV*", list!(args.map(Str).collect()));
  322. // core.mal: defined using the language itself
  323. let _ = rep("(def! *host-language* \"rust\")", &repl_env);
  324. let _ = rep("(def! not (fn* (a) (if a false true)))", &repl_env);
  325. let _ = rep(
  326. "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))",
  327. &repl_env,
  328. );
  329. let _ = rep("(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))", &repl_env);
  330. // Invoked with arguments
  331. if let Some(f) = arg1 {
  332. match rep(&format!("(load-file \"{}\")", f), &repl_env) {
  333. Ok(_) => std::process::exit(0),
  334. Err(e) => {
  335. println!("Error: {}", format_error(e));
  336. std::process::exit(1);
  337. }
  338. }
  339. }
  340. }