lisp.rs 20 KB

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