lisp.rs 14 KB

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