lisp.rs 17 KB

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