lisp.rs 15 KB

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