lisp.rs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. #![allow(non_snake_case)]
  2. use crate::types::LispCircuit;
  3. use bellman::groth16::PreparedVerifyingKey;
  4. use sapvi::{BlsStringConversion, Decodable, Encodable, ZKContract, ZKProof};
  5. use simplelog::*;
  6. use bellman::groth16;
  7. use bls12_381::Bls12;
  8. use fnv::FnvHashMap;
  9. use itertools::Itertools;
  10. use rand::rngs::OsRng;
  11. use std::fs;
  12. use std::fs::File;
  13. use std::rc::Rc;
  14. use std::time::Instant;
  15. use types::EnforceAllocation;
  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::{Bool, Enforce, Func, Hash, List, MalFunc, Nil, Str, Sym, Vector};
  27. use crate::types::VerifyKeyParams;
  28. use crate::types::{error, format_error, MalArgs, MalErr, MalRet, MalVal};
  29. mod env;
  30. mod printer;
  31. mod reader;
  32. use crate::env::{env_bind, env_find, env_get, env_new, env_set, env_sets, Env};
  33. #[macro_use]
  34. mod core;
  35. pub const ZK_CIRCUIT_ENV_KEY: &str = "ZKC";
  36. // read
  37. fn read(str: &str) -> MalRet {
  38. reader::read_str(str.to_string())
  39. }
  40. // eval
  41. fn qq_iter(elts: &MalArgs) -> MalVal {
  42. let mut acc = list![];
  43. for elt in elts.iter().rev() {
  44. if let List(v, _) = elt {
  45. if v.len() == 2 {
  46. if let Sym(ref s) = v[0] {
  47. if s == "splice-unquote" {
  48. acc = list![Sym("concat".to_string()), v[1].clone(), acc];
  49. continue;
  50. }
  51. }
  52. }
  53. }
  54. acc = list![Sym("cons".to_string()), quasiquote(&elt), acc];
  55. }
  56. return acc;
  57. }
  58. fn quasiquote(ast: &MalVal) -> MalVal {
  59. match ast {
  60. List(v, _) => {
  61. if v.len() == 2 {
  62. if let Sym(ref s) = v[0] {
  63. if s == "unquote" {
  64. return v[1].clone();
  65. }
  66. }
  67. }
  68. return qq_iter(&v);
  69. }
  70. Vector(v, _) => return list![Sym("vec".to_string()), qq_iter(&v)],
  71. Hash(_, _) | Sym(_) => return list![Sym("quote".to_string()), ast.clone()],
  72. _ => ast.clone(),
  73. }
  74. }
  75. fn is_macro_call(ast: &MalVal, env: &Env) -> Option<(MalVal, MalArgs)> {
  76. match ast {
  77. List(v, _) => match v[0] {
  78. Sym(ref s) => match env_find(env, s) {
  79. Some(e) => match env_get(&e, &v[0]) {
  80. Ok(f @ MalFunc { is_macro: true, .. }) => Some((f, v[1..].to_vec())),
  81. _ => None,
  82. },
  83. _ => None,
  84. },
  85. _ => None,
  86. },
  87. _ => None,
  88. }
  89. }
  90. fn macroexpand(mut ast: MalVal, env: &Env) -> (bool, MalRet) {
  91. let mut was_expanded = false;
  92. while let Some((mf, args)) = is_macro_call(&ast, env) {
  93. //println!("macroexpand 1: {:?}", ast);
  94. ast = match mf.apply(args) {
  95. Err(e) => return (false, Err(e)),
  96. Ok(a) => a,
  97. };
  98. //println!("macroexpand 2: {:?}", ast);
  99. was_expanded = true;
  100. }
  101. (was_expanded, Ok(ast))
  102. }
  103. fn eval_ast(ast: &MalVal, env: &Env) -> MalRet {
  104. match ast {
  105. Sym(_) => Ok(env_get(&env, &ast)?),
  106. List(v, _) => {
  107. let mut lst: MalArgs = vec![];
  108. for a in v.iter() {
  109. lst.push(eval(a.clone(), env.clone())?)
  110. }
  111. Ok(list!(lst))
  112. }
  113. Vector(v, _) => {
  114. let mut lst: MalArgs = vec![];
  115. for a in v.iter() {
  116. lst.push(eval(a.clone(), env.clone())?)
  117. }
  118. Ok(vector!(lst))
  119. }
  120. Hash(hm, _) => {
  121. let mut new_hm: FnvHashMap<String, MalVal> = FnvHashMap::default();
  122. for (k, v) in hm.iter() {
  123. new_hm.insert(k.to_string(), eval(v.clone(), env.clone())?);
  124. }
  125. Ok(Hash(Rc::new(new_hm), Rc::new(Nil)))
  126. }
  127. _ => Ok(ast.clone()),
  128. }
  129. }
  130. fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
  131. let ret: MalRet;
  132. 'tco: loop {
  133. ret = match ast.clone() {
  134. List(l, _) => {
  135. if l.len() == 0 {
  136. return Ok(ast);
  137. }
  138. match macroexpand(ast.clone(), &env) {
  139. (true, Ok(new_ast)) => {
  140. ast = new_ast;
  141. continue 'tco;
  142. }
  143. (_, Err(e)) => return Err(e),
  144. _ => (),
  145. }
  146. if l.len() == 0 {
  147. return Ok(ast);
  148. }
  149. let a0 = &l[0];
  150. match a0 {
  151. Sym(ref a0sym) if a0sym == "def!" => {
  152. println!("def {:?}", l[1]);
  153. env_set(&env, l[1].clone(), eval(l[2].clone(), env.clone())?)
  154. }
  155. Sym(ref a0sym) if a0sym == "zk*" => {
  156. println!("zk* {:?}", l[1]);
  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 == "let*" => {
  183. env = env_new(Some(env.clone()));
  184. let (a1, a2) = (l[1].clone(), l[2].clone());
  185. match a1 {
  186. List(ref binds, _) | Vector(ref binds, _) => {
  187. for (b, e) in binds.iter().tuples() {
  188. match b {
  189. Sym(_) => {
  190. let _ = env_set(
  191. &env,
  192. b.clone(),
  193. eval(e.clone(), env.clone())?,
  194. );
  195. }
  196. _ => {
  197. return error("let* with non-Sym binding");
  198. }
  199. }
  200. }
  201. }
  202. _ => {
  203. return error("let* with non-List bindings");
  204. }
  205. };
  206. ast = a2;
  207. continue 'tco;
  208. }
  209. Sym(ref a0sym) if a0sym == "quote" => Ok(l[1].clone()),
  210. Sym(ref a0sym) if a0sym == "quasiquoteexpand" => Ok(quasiquote(&l[1])),
  211. Sym(ref a0sym) if a0sym == "quasiquote" => {
  212. ast = quasiquote(&l[1]);
  213. continue 'tco;
  214. }
  215. Sym(ref a0sym) if a0sym == "defmacro!" => {
  216. let (a1, a2) = (l[1].clone(), l[2].clone());
  217. let r = eval(a2, env.clone())?;
  218. match r {
  219. MalFunc {
  220. eval,
  221. ast,
  222. env,
  223. params,
  224. ..
  225. } => Ok(env_set(
  226. &env,
  227. a1.clone(),
  228. MalFunc {
  229. eval: eval,
  230. ast: ast.clone(),
  231. env: env.clone(),
  232. params: params.clone(),
  233. is_macro: true,
  234. meta: Rc::new(Nil),
  235. },
  236. )?),
  237. _ => error("set_macro on non-function"),
  238. }
  239. }
  240. Sym(ref a0sym) if a0sym == "macroexpand" => {
  241. match macroexpand(l[1].clone(), &env) {
  242. (_, Ok(new_ast)) => Ok(new_ast),
  243. (_, e) => return e,
  244. }
  245. }
  246. Sym(ref a0sym) if a0sym == "try*" => match eval(l[1].clone(), env.clone()) {
  247. Err(ref e) if l.len() >= 3 => {
  248. let exc = match e {
  249. ErrMalVal(mv) => mv.clone(),
  250. ErrString(s) => Str(s.to_string()),
  251. };
  252. match l[2].clone() {
  253. List(c, _) => {
  254. let catch_env = env_bind(
  255. Some(env.clone()),
  256. list!(vec![c[1].clone()]),
  257. vec![exc],
  258. )?;
  259. eval(c[2].clone(), catch_env)
  260. }
  261. _ => error("invalid catch block"),
  262. }
  263. }
  264. res => res,
  265. },
  266. Sym(ref a0sym) if a0sym == "do" => {
  267. match eval_ast(&list!(l[1..l.len() - 1].to_vec()), &env)? {
  268. List(_, _) => {
  269. ast = l.last().unwrap_or(&Nil).clone();
  270. continue 'tco;
  271. }
  272. _ => error("invalid do form"),
  273. }
  274. }
  275. Sym(ref a0sym) if a0sym == "if" => {
  276. let cond = eval(l[1].clone(), env.clone())?;
  277. match cond {
  278. Bool(false) | Nil if l.len() >= 4 => {
  279. ast = l[3].clone();
  280. continue 'tco;
  281. }
  282. Bool(false) | Nil => Ok(Nil),
  283. _ if l.len() >= 3 => {
  284. ast = l[2].clone();
  285. continue 'tco;
  286. }
  287. _ => Ok(Nil),
  288. }
  289. }
  290. Sym(ref a0sym) if a0sym == "fn*" => {
  291. let (a1, a2) = (l[1].clone(), l[2].clone());
  292. Ok(MalFunc {
  293. eval: eval,
  294. ast: Rc::new(a2),
  295. env: env,
  296. params: Rc::new(a1),
  297. is_macro: false,
  298. meta: Rc::new(Nil),
  299. })
  300. }
  301. Sym(ref a0sym) if a0sym == "eval" => {
  302. ast = eval(l[1].clone(), env.clone())?;
  303. while let Some(ref e) = env.clone().outer {
  304. env = e.clone();
  305. }
  306. continue 'tco;
  307. }
  308. Sym(ref a0sym) if a0sym == "setup" => {
  309. let a1 = l[1].clone();
  310. // todo
  311. ast = eval(a1.clone(), env.clone())?;
  312. // let _pvk = setup(a1.clone(), env.clone())?;
  313. continue 'tco;
  314. }
  315. Sym(ref a0sym) if a0sym == "prove" => {
  316. let a1 = l[1].clone();
  317. ast = eval(a1.clone(), env.clone())?;
  318. prove(a1.clone(), env.clone())
  319. }
  320. Sym(ref a0sym) if a0sym == "alloc-const" => {
  321. let a1 = l[1].clone();
  322. let value = eval(l[2].clone(), env.clone())?;
  323. let result = eval(value.clone(), env.clone())?;
  324. let allocs = get_allocations(&env, "AllocationsConst");
  325. let mut new_hm: FnvHashMap<String, MalVal> = FnvHashMap::default();
  326. for (k, v) in allocs.iter() {
  327. new_hm.insert(k.to_string(), eval(v.clone(), env.clone())?);
  328. }
  329. new_hm.insert(a1.pr_str(false), result.clone());
  330. env_set(
  331. &env,
  332. Sym("AllocationsConst".to_string()),
  333. Hash(Rc::new(new_hm), Rc::new(Nil)),
  334. )?;
  335. Ok(result.clone())
  336. }
  337. Sym(ref a0sym) if a0sym == "alloc-input" => {
  338. let a1 = l[1].clone();
  339. let value = eval(l[2].clone(), env.clone())?;
  340. let result = eval(value.clone(), env.clone())?;
  341. let allocs = get_allocations(&env, "AllocationsInput");
  342. let mut new_hm: FnvHashMap<String, MalVal> = FnvHashMap::default();
  343. for (k, v) in allocs.iter() {
  344. new_hm.insert(k.to_string(), eval(v.clone(), env.clone())?);
  345. }
  346. new_hm.insert(a1.pr_str(false), result.clone());
  347. env_set(
  348. &env,
  349. Sym("AllocationsInput".to_string()),
  350. Hash(Rc::new(new_hm), Rc::new(Nil)),
  351. )?;
  352. Ok(result.clone())
  353. }
  354. Sym(ref a0sym) if a0sym == "alloc" => {
  355. let a1 = l[1].clone();
  356. let value = eval(l[2].clone(), env.clone())?;
  357. let result = eval(value.clone(), env.clone())?;
  358. let allocs = get_allocations(&env, "Allocations");
  359. let mut new_hm: FnvHashMap<String, MalVal> = FnvHashMap::default();
  360. for (k, v) in allocs.iter() {
  361. new_hm.insert(k.to_string(), eval(v.clone(), env.clone())?);
  362. }
  363. new_hm.insert(a1.pr_str(false), result.clone());
  364. env_set(
  365. &env,
  366. Sym("Allocations".to_string()),
  367. Hash(Rc::new(new_hm), Rc::new(Nil)),
  368. )?;
  369. Ok(result.clone())
  370. }
  371. //Sym(ref a0sym) if a0sym == "verify" => {
  372. Sym(ref a0sym) if a0sym == "enforce" => {
  373. // here i'm considering that we always have tuple with only two elements
  374. // also it's important to keep in mind for the sake of brevity of this v0
  375. // we will not allow calculation or any lisp evaluations inside the enforce
  376. // it means that every symbol will be on allocations and we will do the
  377. // find/replace on the bellman circuit, it's nasty v0
  378. let mut left_vec = vec![];
  379. let mut right_vec = vec![];
  380. let mut out_vec = vec![];
  381. // todo extract a macro for this
  382. match l[1].clone() {
  383. List(v, _) | Vector(v, _) => {
  384. if let List(_, _) = &v.to_vec()[0] {
  385. for ele in v.to_vec().iter() {
  386. if let List(ele_vec, _) = ele {
  387. left_vec.push((
  388. ele_vec[0].pr_str(false),
  389. ele_vec[1].pr_str(false),
  390. ));
  391. }
  392. }
  393. } else {
  394. left_vec.push((v[0].pr_str(false), v[1].pr_str(false)));
  395. }
  396. }
  397. _ => {}
  398. };
  399. match l[2].clone() {
  400. List(v, _) | Vector(v, _) => {
  401. if let List(_, _) = &v.to_vec()[0] {
  402. for ele in v.to_vec().iter() {
  403. if let List(ele_vec, _) = ele {
  404. right_vec.push((
  405. ele_vec[0].pr_str(false),
  406. ele_vec[1].pr_str(false),
  407. ));
  408. }
  409. }
  410. } else {
  411. right_vec.push((v[0].pr_str(false), v[1].pr_str(false)));
  412. }
  413. }
  414. _ => {}
  415. };
  416. match l[3].clone() {
  417. List(v, _) | Vector(v, _) => {
  418. if let List(_, _) = &v.to_vec()[0] {
  419. for ele in v.to_vec().iter() {
  420. if let List(ele_vec, _) = ele {
  421. out_vec.push((
  422. ele_vec[0].pr_str(false),
  423. ele_vec[1].pr_str(false),
  424. ));
  425. }
  426. }
  427. } else {
  428. out_vec.push((v[0].pr_str(false), v[1].pr_str(false)));
  429. }
  430. }
  431. _ => {}
  432. };
  433. let enforce_vec = get_enforce_allocs(&env);
  434. let enforce = EnforceAllocation {
  435. idx: enforce_vec.len() + 1,
  436. left: left_vec,
  437. right: right_vec,
  438. output: out_vec,
  439. };
  440. let mut new_vec: Vec<EnforceAllocation> = vec![enforce];
  441. for value in enforce_vec.iter() {
  442. new_vec.push(value.clone());
  443. }
  444. env_set(
  445. &env,
  446. Sym("AllocationsEnforce".to_string()),
  447. vector![vec![Enforce(Rc::new(new_vec))]],
  448. );
  449. /*
  450. println!("\n\nallocations {:?}", get_allocations(&env, "Allocations"));
  451. println!(
  452. "\n\nallocations input {:?}",
  453. get_allocations(&env, "AllocationsInput")
  454. );
  455. println!("\n\nallocations enforce {:?}", get_enforce_allocs(&env));
  456. */
  457. Ok(vector![vec![]])
  458. }
  459. _ => match eval_ast(&ast, &env)? {
  460. List(ref el, _) => {
  461. let ref f = el[0].clone();
  462. let args = el[1..].to_vec();
  463. match f {
  464. Func(_, _) => f.apply(args),
  465. MalFunc {
  466. ast: mast,
  467. env: menv,
  468. params,
  469. ..
  470. } => {
  471. let a = &**mast;
  472. let p = &**params;
  473. env = env_bind(Some(menv.clone()), p.clone(), args)?;
  474. ast = a.clone();
  475. continue 'tco;
  476. }
  477. _ => {
  478. println!("{:?}", args);
  479. Ok(vector![el.to_vec()])
  480. //error("call non-function")
  481. }
  482. }
  483. }
  484. _ => error("expected a list"),
  485. },
  486. }
  487. }
  488. _ => eval_ast(&ast, &env),
  489. };
  490. break;
  491. } // end 'tco loop
  492. ret
  493. }
  494. pub fn get_enforce_allocs(env: &Env) -> Vec<EnforceAllocation> {
  495. // todo need some cleanup
  496. match env_find(env, "AllocationsEnforce") {
  497. Some(e) => match env_get(&e, &Sym("AllocationsEnforce".to_string())) {
  498. Ok(f) => {
  499. if let Vector(val, _) = f {
  500. if let Enforce(ret) = &val[0] {
  501. ret.to_vec()
  502. } else {
  503. vec![]
  504. }
  505. } else {
  506. vec![]
  507. }
  508. }
  509. _ => vec![],
  510. },
  511. _ => vec![],
  512. }
  513. }
  514. pub fn get_allocations(env: &Env, key: &str) -> Rc<FnvHashMap<String, MalVal>> {
  515. let alloc_hm: Rc<FnvHashMap<String, MalVal>> = Rc::new(FnvHashMap::default());
  516. match env_find(env, key) {
  517. Some(e) => match env_get(&e, &Sym(key.to_string())) {
  518. Ok(f) => {
  519. if let Hash(allocs, _) = f {
  520. allocs
  521. } else {
  522. alloc_hm
  523. }
  524. }
  525. _ => alloc_hm,
  526. },
  527. _ => alloc_hm,
  528. }
  529. }
  530. pub fn setup(_ast: MalVal, env: Env) -> Result<VerifyKeyParams, MalErr> {
  531. let start = Instant::now();
  532. let c = LispCircuit {
  533. params: FnvHashMap::default(),
  534. allocs: FnvHashMap::default(),
  535. alloc_inputs: FnvHashMap::default(),
  536. constraints: Vec::new(),
  537. };
  538. let random_parameters =
  539. groth16::generate_random_parameters::<Bls12, _, _>(c, &mut OsRng).unwrap();
  540. let pvk = groth16::prepare_verifying_key(&random_parameters.vk);
  541. println!("Setup: [{:?}]", start.elapsed());
  542. Ok(VerifyKeyParams {
  543. verifying_key: pvk,
  544. random_params: random_parameters,
  545. })
  546. }
  547. pub fn prove(_ast: MalVal, env: Env) -> MalRet {
  548. let start = Instant::now();
  549. let allocs_input = get_allocations(&env, "AllocationsInput");
  550. let allocs = get_allocations(&env, "Allocations");
  551. let enforce_allocs = get_enforce_allocs(&env);
  552. let allocs_const = get_allocations(&env, "AllocationsConst");
  553. //setup
  554. let params = Some({
  555. let circuit = LispCircuit {
  556. params: allocs_const.as_ref().clone(),
  557. allocs: allocs.as_ref().clone(),
  558. alloc_inputs: allocs_input.as_ref().clone(),
  559. constraints: enforce_allocs.clone(),
  560. };
  561. groth16::generate_random_parameters::<Bls12, _, _>(circuit, &mut OsRng)?
  562. });
  563. let verifying_key = Some(groth16::prepare_verifying_key(&params.as_ref().unwrap().vk));
  564. // prove
  565. let circuit = LispCircuit {
  566. params: allocs_const.as_ref().clone(),
  567. allocs: allocs.as_ref().clone(),
  568. alloc_inputs: allocs_input.as_ref().clone(),
  569. constraints: enforce_allocs.clone(),
  570. };
  571. let proof = groth16::create_random_proof(circuit, params.as_ref().unwrap(), &mut OsRng)?;
  572. let mut vec_input = vec![];
  573. for (k, val) in allocs_input.iter() {
  574. match val {
  575. MalVal::Str(v) => {
  576. vec_input.push(bls12_381::Scalar::from_string(&v.to_string()));
  577. }
  578. MalVal::ZKScalar(v) => {
  579. vec_input.push(bls12_381::Scalar::from(*v));
  580. }
  581. _ => {}
  582. };
  583. }
  584. let result = groth16::verify_proof(verifying_key.as_ref().unwrap(), &proof, &vec_input);
  585. println!("vec public {:?}", vec_input);
  586. println!("result {:?}", result);
  587. Ok(MalVal::Nil)
  588. }
  589. pub fn verify(_ast: &MalVal) -> MalRet {
  590. let _public_input = vec![bls12_381::Scalar::from(27)];
  591. let start = Instant::now();
  592. println!("Verify: [{:?}]", start.elapsed());
  593. Ok(MalVal::Nil)
  594. }
  595. // print
  596. fn print(ast: &MalVal) -> String {
  597. ast.pr_str(true)
  598. }
  599. fn rep(str: &str, env: &Env) -> Result<String, MalErr> {
  600. let ast = read(str)?;
  601. let exp = eval(ast, env.clone())?;
  602. Ok(print(&exp))
  603. }
  604. fn main() -> Result<(), ()> {
  605. let matches = clap_app!(zklisp =>
  606. (version: "0.1.0")
  607. (author: "mileschet <miles.chet@gmail.com>")
  608. (about: "A Lisp Interpreter for Zero Knowledge Virtual Machine")
  609. (@subcommand load =>
  610. (about: "Load the file into the interpreter")
  611. (@arg FILE: +required "Lisp Contract filename")
  612. )
  613. )
  614. .get_matches();
  615. CombinedLogger::init(vec![TermLogger::new(
  616. LevelFilter::Debug,
  617. Config::default(),
  618. TerminalMode::Mixed,
  619. )
  620. .unwrap()])
  621. .unwrap();
  622. match matches.subcommand() {
  623. Some(("load", matches)) => {
  624. let file: String = matches.value_of("FILE").unwrap().parse().unwrap();
  625. repl_load(file)?;
  626. }
  627. _ => {
  628. eprintln!("error: Invalid subcommand invoked");
  629. std::process::exit(-1);
  630. }
  631. }
  632. Ok(())
  633. }
  634. fn repl_load(file: String) -> Result<(), ()> {
  635. let repl_env = env_new(None);
  636. for (k, v) in core::ns() {
  637. env_sets(&repl_env, k, v);
  638. }
  639. let _ = rep("(def! not (fn* (a) (if a false true)))", &repl_env);
  640. let _ = rep(
  641. "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))",
  642. &repl_env,
  643. );
  644. //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);
  645. match rep(&format!("(load-file \"{}\")", file), &repl_env) {
  646. Ok(_) => std::process::exit(0),
  647. Err(e) => {
  648. println!("Error: {}", format_error(e));
  649. std::process::exit(1);
  650. }
  651. }
  652. }