소스 검색

added mal lisp and jubjub unfinished sample

ada 5 년 전
부모
커밋
e27ac3d452
4개의 변경된 파일312개의 추가작업 그리고 673개의 파일을 삭제
  1. 0 1
      Cargo.toml
  2. 0 113
      lisp/jj.rkt
  3. 312 418
      lisp/lisp.rs
  4. 0 141
      lisp/zk.rkt

+ 0 - 1
Cargo.toml

@@ -36,7 +36,6 @@ failure = "0.1.8"
 failure_derive = "0.1.8"
 
 regex = "1"
-fancy-regex = "0.4.0"
 
 [[bin]]
 name = "sha256"

+ 0 - 113
lisp/jj.rkt

@@ -1,113 +0,0 @@
-#lang racket
-
-(require "zk.rkt")
-
-(struct jj_point
-    (u v)
-)
-
-(define (create_jj_param_point name)
-    (jj_point
-        (zk_param (string-append name "_u"))
-        (zk_param (string-append name "_v"))
-    )
-)
-(define (create_jj_public_point name)
-    (jj_point
-        (zk_public (string-append name "_u"))
-        (zk_public (string-append name "_v"))
-    )
-)
-
-(define (zk_jj_add namespace result a b)
-    (zk_comment "call jj_add()")
-    (let* ([namespace (append namespace (list "_jj_add"))]
-           [U (zk_private namespace 'U)]
-           [A (zk_private namespace 'A)]
-           [B (zk_private namespace 'B)]
-           [C (zk_private namespace 'C)]
-           [tmp (zk_local namespace 'tmp)])
-        (zk_comment "Compute U = (x1 + y1) * (y2 - EDWARDS_A*x2)")
-        (zk_comment "          = (x1 + y1) * (x2 + y2)")
-        (zk_set U (jj_point-u a))
-        (zk_add U (jj_point-v a))
-
-        (zk_set tmp (jj_point-u b))
-        (zk_add tmp (jj_point-v b))
-
-        (zk_mul U tmp)
-
-        (zk_comment "assert (x1 + y1) * (x2 + y2) == U")
-        (zk_lc0_add (jj_point-u a))
-        (zk_lc0_add (jj_point-v a))
-        (zk_lc1_add (jj_point-u b))
-        (zk_lc1_add (jj_point-v b))
-        (zk_lc2_add U)
-        (zk_enforce)
-
-        (zk_comment "Compute A = y2 * x1")
-        (zk_set A (jj_point-v b))
-        (zk_mul A (jj_point-u a))
-        (zk_comment "Compute B = x2 * y1")
-        (zk_set B (jj_point-u b))
-        (zk_mul B (jj_point-v a))
-        (zk_comment "Compute C = d*A*B")
-        (zk_load C const_d)
-        (zk_mul C A)
-        (zk_mul C B)
-
-        (zk_comment "assert (d * A) * (B) == C")
-        (zk_lc0_add_coeff const_d A)
-        (zk_lc1_add B)
-        (zk_lc2_add C)
-        (zk_enforce)
-
-        (zk_comment "Compute P.x = (A + B) / (1 + C)")
-        (zk_set (jj_point-u result) A)
-        (zk_add (jj_point-u result) B)
-        ; Re-use the tmp variable from earlier here
-        (zk_load tmp const_one)
-        (zk_add tmp C)
-        (zk_divide (jj_point-u result) tmp)
-
-        (zk_lc0_add_one)
-        (zk_lc0_add C)
-        (zk_lc1_add (jj_point-u result))
-        (zk_lc2_add A)
-        (zk_lc2_add B)
-        (zk_enforce)
-
-        (zk_comment "Compute P.y = (U - A - B) / (1 - C)")
-        (zk_set (jj_point-v result) U)
-        (zk_sub (jj_point-v result) A)
-        (zk_sub (jj_point-v result) B)
-        ; Re-use the tmp variable from earlier here
-        (zk_load tmp const_one)
-        (zk_sub tmp C)
-        (zk_divide (jj_point-v result) tmp)
-
-        (zk_lc0_add_one)
-        (zk_lc0_sub C)
-        (zk_lc1_add (jj_point-v result))
-        (zk_lc2_add U)
-        (zk_lc2_sub A)
-        (zk_lc2_sub B)
-        (zk_enforce)
-    )
-)
-
-(create_zk_output "jj.psm")
-
-(define const_d (zk_constant
-    "d" "0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1"))
-(define const_one (zk_constant
-    "one" "0x0000000000000000000000000000000000000000000000000000000000000001"))
-
-(zk_contract_begin "foo")
-(define namespace (list "_"))
-(define a (create_jj_param_point "a"))
-(define b (create_jj_param_point "b"))
-(define result (create_jj_public_point "result"))
-(zk_jj_add namespace result a b)
-(zk_contract_end)
-

+ 312 - 418
lisp/lisp.rs

@@ -1,460 +1,354 @@
-use std::collections::HashMap;
+#![allow(non_snake_case)]
 
-use fancy_regex::Regex;
-use std::fmt;
-use std::fs::File;
-use std::io;
-use std::io::{BufRead, BufReader};
-use std::num::ParseFloatError;
 use std::rc::Rc;
-/*
-  Types
-*/
-
-#[derive(Clone)]
-enum RispExp {
-    Bool(bool),
-    Symbol(String),
-    Number(f64),
-    List(Vec<RispExp>),
-    Func(fn(&[RispExp]) -> Result<RispExp, RispErr>),
-    Lambda(RispLambda),
-}
-
-#[derive(Clone)]
-struct RispLambda {
-    params_exp: Rc<RispExp>,
-    body_exp: Rc<RispExp>,
+//use std::collections::HashMap;
+use fnv::FnvHashMap;
+use itertools::Itertools;
+
+#[macro_use]
+extern crate lazy_static;
+extern crate fnv;
+extern crate itertools;
+extern crate regex;
+
+#[macro_use]
+mod types;
+use crate::types::MalErr::{ErrMalVal, ErrString};
+use crate::types::MalVal::{Bool, Func, Hash, List, MalFunc, Nil, Str, Sym, Vector};
+use crate::types::{error, format_error, MalArgs, MalErr, MalRet, MalVal};
+mod env;
+mod printer;
+mod reader;
+use crate::env::{env_bind, env_find, env_get, env_new, env_set, env_sets, Env};
+#[macro_use]
+mod core;
+
+// read
+fn read(str: &str) -> MalRet {
+    reader::read_str(str.to_string())
 }
 
-impl fmt::Display for RispExp {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let str = match self {
-            RispExp::Bool(a) => a.to_string(),
-            RispExp::Symbol(s) => s.clone(),
-            RispExp::Number(n) => n.to_string(),
-            RispExp::List(list) => {
-                let xs: Vec<String> = list.iter().map(|x| x.to_string()).collect();
-                format!("({})", xs.join(","))
-            }
-            RispExp::Func(_) => "Function {}".to_string(),
-            RispExp::Lambda(_) => "Lambda {}".to_string(),
-        };
-
-        write!(f, "{}", str)
-    }
-}
-
-#[derive(Debug)]
-enum RispErr {
-    Reason(String),
-}
-
-#[derive(Clone)]
-struct RispEnv<'a> {
-    data: HashMap<String, RispExp>,
-    outer: Option<&'a RispEnv<'a>>,
-}
-
-/*
- InPort
-*/
-// TODO change to symbol(eof)
-
-struct InPort {
-    line: String,
-    lines: Vec<String>,
-    cur_line: usize,
-}
-
-impl InPort {
-    fn init(filename: String) -> InPort {
-        let file = File::open(filename).unwrap();
-        let reader = io::BufReader::new(file)
-            .lines()
-            .map(|s| s.ok().unwrap().to_string())
-            .collect();
-        InPort {
-            line: String::new(),
-            lines: reader,
-            cur_line: 0,
-        }
-    }
-
-    pub fn next_token(&mut self) -> String {
-        loop {
-            if self.line.is_empty() {
-                self.line = self
-                    .lines
-                    .get(self.cur_line)
-                    .unwrap_or(&"#<eof-object>".to_string())
-                    .to_string();
-                self.cur_line = self.cur_line + 1;
-            }
-            if self.line.is_empty() {
-                return "#<eof-object>".to_string();
-            }
-            let (token, rest) = InPort::tokenize(self.line.clone());
-            self.line = rest;
-            if !token.is_empty() {
-                return token;
+// eval
+
+fn qq_iter(elts: &MalArgs) -> MalVal {
+    let mut acc = list![];
+    for elt in elts.iter().rev() {
+        if let List(v, _) = elt {
+            if v.len() == 2 {
+                if let Sym(ref s) = v[0] {
+                    if s == "splice-unquote" {
+                        acc = list![Sym("concat".to_string()), v[1].clone(), acc];
+                        continue;
+                    }
+                }
             }
         }
+        acc = list![Sym("cons".to_string()), quasiquote(&elt), acc];
     }
-
-    fn tokenize(expr: String) -> (String, String) {
-        let re =
-            Regex::new(r#"\s*(,@|[('`,)]|"(?:[\\].|[^\\"])*"|;.*|[^\s('"`,;)]*)(.*)"#).unwrap();
-        let result = re.captures(&expr);
-        let captures = result
-            .expect("Error running regex")
-            .expect("No match found");
-        //        println!("{}", captures.get(0).unwrap().as_str().to_string());
-        (
-            captures.get(1).unwrap().as_str().to_string(),
-            captures.get(2).unwrap().as_str().to_string(),
-        )
-    }
+    return acc;
 }
 
-fn read_ahead(inport: &InPort, token: String) -> String {
-    match token.as_str() {
-        "(" => {
-            let mut L = Vec::new();
-            loop {
-                let t = &inport.next_token();
-                if t.to_string() == ")" {
-                        return L.into_iter().collect();
-                    } else {
-                        L.push(read_ahead(&inport, t.to_string()));
+fn quasiquote(ast: &MalVal) -> MalVal {
+    match ast {
+        List(v, _) => {
+            if v.len() == 2 {
+                if let Sym(ref s) = v[0] {
+                    if s == "unquote" {
+                        return v[1].clone();
                     }
                 }
             }
-        _ => {
-            println!("{}", token);
-            return token;
-        }
+            return qq_iter(&v);
+        },
+        Vector(v, _) => return list![Sym("vec".to_string()), qq_iter(&v)],
+        Hash(_, _) | Sym(_)=> return list![Sym("quote".to_string()), ast.clone()],
+        _ => ast.clone(),
     }
 }
 
-fn read_seq<'a>(tokens: &'a [String]) -> Result<(RispExp, &'a [String]), RispErr> {
-    let mut res: Vec<RispExp> = vec![];
-    let mut xs = tokens;
-    loop {
-        let (next_token, rest) = xs
-            .split_first()
-            .ok_or(RispErr::Reason("could not find closing `)`".to_string()))?;
-        if next_token == ")" {
-            return Ok((RispExp::List(res), rest)); // skip `)`, head to the token after
-        }
-        let (exp, new_xs) = parse(&xs)?;
-        res.push(exp);
-        xs = new_xs;
+fn is_macro_call(ast: &MalVal, env: &Env) -> Option<(MalVal, MalArgs)> {
+    match ast {
+        List(v, _) => match v[0] {
+            Sym(ref s) => match env_find(env, s) {
+                Some(e) => match env_get(&e, &v[0]) {
+                    Ok(f @ MalFunc { is_macro: true, .. }) => Some((f, v[1..].to_vec())),
+                    _ => None,
+                },
+                _ => None,
+            },
+            _ => None,
+        },
+        _ => None,
     }
 }
-// TODO change return type to Symbol
-fn read(inport: &InPort) -> String {
-    let token1 = &inport.next_token().as_str();
-    if token1.to_string() == "#<eof-object>".to_string() {
-        return "#<eof-object>".to_string();
-    } else {
-        return read_ahead(&inport, token1.to_string());
+
+fn macroexpand(mut ast: MalVal, env: &Env) -> (bool, MalRet) {
+    let mut was_expanded = false;
+    while let Some((mf, args)) = is_macro_call(&ast, env) {
+        //println!("macroexpand 1: {:?}", ast);
+        ast = match mf.apply(args) {
+            Err(e) => return (false, Err(e)),
+            Ok(a) => a,
+        };
+        //println!("macroexpand 2: {:?}", ast);
+        was_expanded = true;
     }
+    ((was_expanded, Ok(ast)))
 }
 
-fn parse_atom(token: &str) -> RispExp {
-    match token.as_ref() {
-        "true" => RispExp::Bool(true),
-        "false" => RispExp::Bool(false),
-        _ => {
-            let potential_float: Result<f64, ParseFloatError> = token.parse();
-            match potential_float {
-                Ok(v) => RispExp::Number(v),
-                Err(_) => RispExp::Symbol(token.to_string().clone()),
+fn eval_ast(ast: &MalVal, env: &Env) -> MalRet {
+    match ast {
+        Sym(_) => Ok(env_get(&env, &ast)?),
+        List(v, _) => {
+            let mut lst: MalArgs = vec![];
+            for a in v.iter() {
+                lst.push(eval(a.clone(), env.clone())?)
             }
+            Ok(list!(lst))
         }
-    }
-}
-
-/*
-  Env
-*/
-
-macro_rules! ensure_tonicity {
-    ($check_fn:expr) => {{
-        |args: &[RispExp]| -> Result<RispExp, RispErr> {
-            let floats = parse_list_of_floats(args)?;
-            let first = floats
-                .first()
-                .ok_or(RispErr::Reason("expected at least one number".to_string()))?;
-            let rest = &floats[1..];
-            fn f(prev: &f64, xs: &[f64]) -> bool {
-                match xs.first() {
-                    Some(x) => $check_fn(prev, x) && f(x, &xs[1..]),
-                    None => true,
-                }
-            };
-            Ok(RispExp::Bool(f(first, rest)))
+        Vector(v, _) => {
+            let mut lst: MalArgs = vec![];
+            for a in v.iter() {
+                lst.push(eval(a.clone(), env.clone())?)
+            }
+            Ok(vector!(lst))
         }
-    }};
-}
-
-fn default_env<'a>() -> RispEnv<'a> {
-    let mut data: HashMap<String, RispExp> = HashMap::new();
-    data.insert(
-        "+".to_string(),
-        RispExp::Func(|args: &[RispExp]| -> Result<RispExp, RispErr> {
-            let sum = parse_list_of_floats(args)?
-                .iter()
-                .fold(0.0, |sum, a| sum + a);
-
-            Ok(RispExp::Number(sum))
-        }),
-    );
-    data.insert(
-        "-".to_string(),
-        RispExp::Func(|args: &[RispExp]| -> Result<RispExp, RispErr> {
-            let floats = parse_list_of_floats(args)?;
-            let first = *floats
-                .first()
-                .ok_or(RispErr::Reason("expected at least one number".to_string()))?;
-            let sum_of_rest = floats[1..].iter().fold(0.0, |sum, a| sum + a);
-
-            Ok(RispExp::Number(first - sum_of_rest))
-        }),
-    );
-    data.insert(
-        "=".to_string(),
-        RispExp::Func(ensure_tonicity!(|a, b| a == b)),
-    );
-    data.insert(
-        ">".to_string(),
-        RispExp::Func(ensure_tonicity!(|a, b| a > b)),
-    );
-    data.insert(
-        ">=".to_string(),
-        RispExp::Func(ensure_tonicity!(|a, b| a >= b)),
-    );
-    data.insert(
-        "<".to_string(),
-        RispExp::Func(ensure_tonicity!(|a, b| a < b)),
-    );
-    data.insert(
-        "<=".to_string(),
-        RispExp::Func(ensure_tonicity!(|a, b| a <= b)),
-    );
-
-    RispEnv { data, outer: None }
-}
-
-fn parse_list_of_floats(args: &[RispExp]) -> Result<Vec<f64>, RispErr> {
-    args.iter().map(|x| parse_single_float(x)).collect()
-}
-
-fn parse_single_float(exp: &RispExp) -> Result<f64, RispErr> {
-    match exp {
-        RispExp::Number(num) => Ok(*num),
-        _ => Err(RispErr::Reason("expected a number".to_string())),
-    }
-}
-
-/*
-  Eval
-*/
-
-fn eval_if_args(arg_forms: &[RispExp], env: &mut RispEnv) -> Result<RispExp, RispErr> {
-    let test_form = arg_forms
-        .first()
-        .ok_or(RispErr::Reason("expected test form".to_string()))?;
-    let test_eval = eval(test_form, env)?;
-    match test_eval {
-        RispExp::Bool(b) => {
-            let form_idx = if b { 1 } else { 2 };
-            let res_form = arg_forms
-                .get(form_idx)
-                .ok_or(RispErr::Reason(format!("expected form idx={}", form_idx)))?;
-            let res_eval = eval(res_form, env);
-
-            res_eval
+        Hash(hm, _) => {
+            let mut new_hm: FnvHashMap<String, MalVal> = FnvHashMap::default();
+            for (k, v) in hm.iter() {
+                new_hm.insert(k.to_string(), eval(v.clone(), env.clone())?);
+            }
+            Ok(Hash(Rc::new(new_hm), Rc::new(Nil)))
         }
-        _ => Err(RispErr::Reason(format!(
-            "unexpected test form='{}'",
-            test_form.to_string()
-        ))),
-    }
-}
-
-fn eval_def_args(arg_forms: &[RispExp], env: &mut RispEnv) -> Result<RispExp, RispErr> {
-    let first_form = arg_forms
-        .first()
-        .ok_or(RispErr::Reason("expected first form".to_string()))?;
-    let first_str = match first_form {
-        RispExp::Symbol(s) => Ok(s.clone()),
-        _ => Err(RispErr::Reason(
-            "expected first form to be a symbol".to_string(),
-        )),
-    }?;
-    let second_form = arg_forms
-        .get(1)
-        .ok_or(RispErr::Reason("expected second form".to_string()))?;
-    if arg_forms.len() > 2 {
-        return Err(RispErr::Reason("def can only have two forms ".to_string()));
+        _ => Ok(ast.clone()),
     }
-    let second_eval = eval(second_form, env)?;
-    env.data.insert(first_str, second_eval);
-
-    Ok(first_form.clone())
 }
 
-fn eval_lambda_args(arg_forms: &[RispExp]) -> Result<RispExp, RispErr> {
-    let params_exp = arg_forms
-        .first()
-        .ok_or(RispErr::Reason("expected args form".to_string()))?;
-    let body_exp = arg_forms
-        .get(1)
-        .ok_or(RispErr::Reason("expected second form".to_string()))?;
-    if arg_forms.len() > 2 {
-        return Err(RispErr::Reason(
-            "fn definition can only have two forms ".to_string(),
-        ));
-    }
+fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
+    let ret: MalRet;
 
-    Ok(RispExp::Lambda(RispLambda {
-        body_exp: Rc::new(body_exp.clone()),
-        params_exp: Rc::new(params_exp.clone()),
-    }))
-}
+    'tco: loop {
+        ret = match ast.clone() {
+            List(l, _) => {
+                if l.len() == 0 {
+                    return Ok(ast);
+                }
+                match macroexpand(ast.clone(), &env) {
+                    (true, Ok(new_ast)) => {
+                        ast = new_ast;
+                        continue 'tco;
+                    }
+                    (_, Err(e)) => return Err(e),
+                    _ => (),
+                }
 
-fn eval_built_in_form(
-    exp: &RispExp,
-    arg_forms: &[RispExp],
-    env: &mut RispEnv,
-) -> Option<Result<RispExp, RispErr>> {
-    match exp {
-        RispExp::Symbol(s) => match s.as_ref() {
-            "if" => Some(eval_if_args(arg_forms, env)),
-            "def" => Some(eval_def_args(arg_forms, env)),
-            "fn" => Some(eval_lambda_args(arg_forms)),
-            _ => None,
-        },
-        _ => None,
-    }
-}
+                if l.len() == 0 {
+                    return Ok(ast);
+                }
+                let a0 = &l[0];
+                match a0 {
+                    Sym(ref a0sym) if a0sym == "def!" => {
+                        env_set(&env, l[1].clone(), eval(l[2].clone(), env.clone())?)
+                    }
+                    Sym(ref a0sym) if a0sym == "let*" => {
+                        env = env_new(Some(env.clone()));
+                        let (a1, a2) = (l[1].clone(), l[2].clone());
+                        match a1 {
+                            List(ref binds, _) | Vector(ref binds, _) => {
+                                for (b, e) in binds.iter().tuples() {
+                                    match b {
+                                        Sym(_) => {
+                                            let _ = env_set(
+                                                &env,
+                                                b.clone(),
+                                                eval(e.clone(), env.clone())?,
+                                            );
+                                        }
+                                        _ => {
+                                            return error("let* with non-Sym binding");
+                                        }
+                                    }
+                                }
+                            }
+                            _ => {
+                                return error("let* with non-List bindings");
+                            }
+                        };
+                        ast = a2;
+                        continue 'tco;
+                    }
+                    Sym(ref a0sym) if a0sym == "quote" => Ok(l[1].clone()),
+                    Sym(ref a0sym) if a0sym == "quasiquoteexpand" => Ok(quasiquote(&l[1])),
+                    Sym(ref a0sym) if a0sym == "quasiquote" => {
+                        ast = quasiquote(&l[1]);
+                        continue 'tco;
+                    }
+                    Sym(ref a0sym) if a0sym == "defmacro!" => {
+                        let (a1, a2) = (l[1].clone(), l[2].clone());
+                        let r = eval(a2, env.clone())?;
+                        match r {
+                            MalFunc {
+                                eval,
+                                ast,
+                                env,
+                                params,
+                                ..
+                            } => Ok(env_set(
+                                &env,
+                                a1.clone(),
+                                MalFunc {
+                                    eval: eval,
+                                    ast: ast.clone(),
+                                    env: env.clone(),
+                                    params: params.clone(),
+                                    is_macro: true,
+                                    meta: Rc::new(Nil),
+                                },
+                            )?),
+                            _ => error("set_macro on non-function"),
+                        }
+                    }
+                    Sym(ref a0sym) if a0sym == "macroexpand" => {
+                        match macroexpand(l[1].clone(), &env) {
+                            (_, Ok(new_ast)) => Ok(new_ast),
+                            (_, e) => return e,
+                        }
+                    }
+                    Sym(ref a0sym) if a0sym == "try*" => match eval(l[1].clone(), env.clone()) {
+                        Err(ref e) if l.len() >= 3 => {
+                            let exc = match e {
+                                ErrMalVal(mv) => mv.clone(),
+                                ErrString(s) => Str(s.to_string()),
+                            };
+                            match l[2].clone() {
+                                List(c, _) => {
+                                    let catch_env = env_bind(
+                                        Some(env.clone()),
+                                        list!(vec![c[1].clone()]),
+                                        vec![exc],
+                                    )?;
+                                    eval(c[2].clone(), catch_env)
+                                }
+                                _ => error("invalid catch block"),
+                            }
+                        }
+                        res => res,
+                    },
+                    Sym(ref a0sym) if a0sym == "do" => {
+                        match eval_ast(&list!(l[1..l.len() - 1].to_vec()), &env)? {
+                            List(_, _) => {
+                                ast = l.last().unwrap_or(&Nil).clone();
+                                continue 'tco;
+                            }
+                            _ => error("invalid do form"),
+                        }
+                    }
+                    Sym(ref a0sym) if a0sym == "if" => {
+                        let cond = eval(l[1].clone(), env.clone())?;
+                        match cond {
+                            Bool(false) | Nil if l.len() >= 4 => {
+                                ast = l[3].clone();
+                                continue 'tco;
+                            }
+                            Bool(false) | Nil => Ok(Nil),
+                            _ if l.len() >= 3 => {
+                                ast = l[2].clone();
+                                continue 'tco;
+                            }
+                            _ => Ok(Nil),
+                        }
+                    }
+                    Sym(ref a0sym) if a0sym == "fn*" => {
+                        let (a1, a2) = (l[1].clone(), l[2].clone());
+                        Ok(MalFunc {
+                            eval: eval,
+                            ast: Rc::new(a2),
+                            env: env,
+                            params: Rc::new(a1),
+                            is_macro: false,
+                            meta: Rc::new(Nil),
+                        })
+                    }
+                    Sym(ref a0sym) if a0sym == "eval" => {
+                        ast = eval(l[1].clone(), env.clone())?;
+                        while let Some(ref e) = env.clone().outer {
+                            env = e.clone();
+                        }
+                        continue 'tco;
+                    }
+                    _ => match eval_ast(&ast, &env)? {
+                        List(ref el, _) => {
+                            let ref f = el[0].clone();
+                            let args = el[1..].to_vec();
+                            match f {
+                                Func(_, _) => f.apply(args),
+                                MalFunc {
+                                    ast: mast,
+                                    env: menv,
+                                    params,
+                                    ..
+                                } => {
+                                    let a = &**mast;
+                                    let p = &**params;
+                                    env = env_bind(Some(menv.clone()), p.clone(), args)?;
+                                    ast = a.clone();
+                                    continue 'tco;
+                                }
+                                _ => error("attempt to call non-function"),
+                            }
+                        }
+                        _ => error("expected a list"),
+                    },
+                }
+            }
+            _ => eval_ast(&ast, &env),
+        };
 
-fn env_get(k: &str, env: &RispEnv) -> Option<RispExp> {
-    match env.data.get(k) {
-        Some(exp) => Some(exp.clone()),
-        None => match &env.outer {
-            Some(outer_env) => env_get(k, &outer_env),
-            None => None,
-        },
-    }
-}
+        break;
+    } // end 'tco loop
 
-fn parse_list_of_symbol_strings(form: Rc<RispExp>) -> Result<Vec<String>, RispErr> {
-    let list = match form.as_ref() {
-        RispExp::List(s) => Ok(s.clone()),
-        _ => Err(RispErr::Reason(
-            "expected args form to be a list".to_string(),
-        )),
-    }?;
-    list.iter()
-        .map(|x| match x {
-            RispExp::Symbol(s) => Ok(s.clone()),
-            _ => Err(RispErr::Reason(
-                "expected symbols in the argument list".to_string(),
-            )),
-        })
-        .collect()
+    ret
 }
 
-fn env_for_lambda<'a>(
-    params: Rc<RispExp>,
-    arg_forms: &[RispExp],
-    outer_env: &'a mut RispEnv,
-) -> Result<RispEnv<'a>, RispErr> {
-    let ks = parse_list_of_symbol_strings(params)?;
-    if ks.len() != arg_forms.len() {
-        return Err(RispErr::Reason(format!(
-            "expected {} arguments, got {}",
-            ks.len(),
-            arg_forms.len()
-        )));
-    }
-    let vs = eval_forms(arg_forms, outer_env)?;
-    let mut data: HashMap<String, RispExp> = HashMap::new();
-    for (k, v) in ks.iter().zip(vs.iter()) {
-        data.insert(k.clone(), v.clone());
-    }
-    Ok(RispEnv {
-        data,
-        outer: Some(outer_env),
-    })
+// print
+fn print(ast: &MalVal) -> String {
+    ast.pr_str(true)
 }
 
-fn eval_forms(arg_forms: &[RispExp], env: &mut RispEnv) -> Result<Vec<RispExp>, RispErr> {
-    arg_forms.iter().map(|x| eval(x, env)).collect()
+fn rep(str: &str, env: &Env) -> Result<String, MalErr> {
+    let ast = read(str)?;
+    let exp = eval(ast, env.clone())?;
+    Ok(print(&exp))
 }
 
-fn eval(exp: &RispExp, env: &mut RispEnv) -> Result<RispExp, RispErr> {
-    match exp {
-        RispExp::Symbol(k) => {
-            env_get(k, env).ok_or(RispErr::Reason(format!("unexpected symbol k='{}'", k)))
-        }
-        RispExp::Bool(_a) => Ok(exp.clone()),
-        RispExp::Number(_a) => Ok(exp.clone()),
+fn main() {
+    let mut args = std::env::args();
+    let arg1 = args.nth(1);
 
-        RispExp::List(list) => {
-            let first_form = list
-                .first()
-                .ok_or(RispErr::Reason("expected a non-empty list".to_string()))?;
-            let arg_forms = &list[1..];
-            match eval_built_in_form(first_form, arg_forms, env) {
-                Some(res) => res,
-                None => {
-                    let first_eval = eval(first_form, env)?;
-                    match first_eval {
-                        RispExp::Func(f) => f(&eval_forms(arg_forms, env)?),
-                        RispExp::Lambda(lambda) => {
-                            let new_env = &mut env_for_lambda(lambda.params_exp, arg_forms, env)?;
-                            eval(&lambda.body_exp, new_env)
-                        }
-                        _ => Err(RispErr::Reason("first form must be a function".to_string())),
-                    }
-                }
+    // core.rs: defined using rust
+    let repl_env = env_new(None);
+    for (k, v) in core::ns() {
+        env_sets(&repl_env, k, v);
+    }
+    env_sets(&repl_env, "*ARGV*", list!(args.map(Str).collect()));
+
+    // core.mal: defined using the language itself
+    let _ = rep("(def! *host-language* \"rust\")", &repl_env);
+    let _ = rep("(def! not (fn* (a) (if a false true)))", &repl_env);
+    let _ = rep(
+        "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))",
+        &repl_env,
+    );
+    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);
+
+    // Invoked with arguments
+    if let Some(f) = arg1 {
+        match rep(&format!("(load-file \"{}\")", f), &repl_env) {
+            Ok(_) => std::process::exit(0),
+            Err(e) => {
+                println!("Error: {}", format_error(e));
+                std::process::exit(1);
             }
         }
-        RispExp::Func(_) => Err(RispErr::Reason("unexpected form".to_string())),
-        RispExp::Lambda(_) => Err(RispErr::Reason("unexpected form".to_string())),
-    }
-}
-
-fn main() {
-    let env = &mut default_env();
-    let mut reader = InPort::init("new.lisp".to_string());
-    let mut token = String::new();
-    read(&reader);
-    // read from file
-    //    let file = File::open("new.lisp").unwrap();
-    //    let lines = io::BufReader::new(file).lines();
-    //    let mut cur_line = String::new();
-    //    let mut token = String::new();
-    //    for line in lines {
-    //        let (token, cur_line) = tokenize(line.ok().unwrap().as_str().to_string());
-    //        println!("token {:?}", token);
-    //        println!("line {:?}", cur_line);
-    //   }
-
-    /*
-    loop {
-      println!("risp >");
-      let expr = slurp_expr();
-      match parse_eval(expr, env) {
-        Ok(res) => println!("// 🔥 => {}", res),
-        Err(e) => match e {
-          RispErr::Reason(msg) => println!("// 🙀 => {}", msg),
-        },
-      }
     }
-    */
 }

+ 0 - 141
lisp/zk.rkt

@@ -1,141 +0,0 @@
-#lang racket
-
-(provide zk_variable)
-(provide zk_constant)
-(provide zk_param)
-(provide zk_public)
-(provide zk_local)
-(provide zk_private)
-(provide zk_comment)
-(provide zk_set)
-(provide zk_add)
-(provide zk_sub)
-(provide zk_mul)
-(provide zk_divide)
-(provide zk_load)
-(provide zk_lc0_add)
-(provide zk_lc1_add)
-(provide zk_lc2_add)
-(provide zk_lc0_sub)
-(provide zk_lc1_sub)
-(provide zk_lc2_sub)
-(provide zk_lc0_add_coeff)
-(provide zk_lc1_add_coeff)
-(provide zk_lc2_add_coeff)
-(provide zk_lc0_add_one)
-(provide zk_lc1_add_one)
-(provide zk_lc2_add_one)
-(provide zk_enforce)
-
-(provide create_zk_output)
-(provide zk_contract_begin)
-(provide zk_contract_end)
-
-(define out '0)
-(define (create_zk_output filename)
-    (set! out (open-output-file "jj.psm" #:exists 'truncate))
-)
-
-(struct zk_variable 
-    (name type)
-)
-
-(define (zk_constant name hex_value)
-    (fprintf out "constant ~a ~a\n" name hex_value)
-    name
-)
-
-(define (zk_contract_begin contract_name)
-    (fprintf out "contract ~a\n" contract_name)
-)
-(define (zk_contract_end)
-    (fprintf out "end\n")
-)
-
-(define (zk_param name)
-    (fprintf out "param ~a\n" name)
-    (zk_variable name 'param)
-)
-
-(define (zk_public name)
-    (fprintf out "public ~a\n" name)
-    (zk_variable name 'public)
-)
-
-(define (strings->string sts)
-    (apply string-append sts))
-
-(define (apply_ns namespace name)
-    (strings->string
-        (append namespace
-            (list "__" (symbol->string name))
-        )))
-
-(define (zk_local namespace name)
-    (let ([name (apply_ns namespace name)])
-        (fprintf out "local ~a\n" name)
-        (zk_variable name 'local)
-    )
-)
-
-(define (zk_private namespace name)
-    (let ([name (apply_ns namespace name)])
-        (fprintf out "private ~a\n" name)
-        (zk_variable name 'private)
-    )
-)
-
-(define (zk_comment str)
-    (fprintf out "# ~a\n" str)
-)
-
-(define (zk_set self other)
-    (fprintf out "set ~a ~a\n" (zk_variable-name self) (zk_variable-name other))
-)
-(define (zk_add self other)
-    (fprintf out "add ~a ~a\n" (zk_variable-name self) (zk_variable-name other))
-)
-(define (zk_sub self other)
-    (fprintf out "sub ~a ~a\n" (zk_variable-name self) (zk_variable-name other))
-)
-(define (zk_mul self other)
-    (fprintf out "mul ~a ~a\n" (zk_variable-name self) (zk_variable-name other))
-)
-(define (zk_divide self other)
-    (fprintf out "divide ~a ~a\n"
-        (zk_variable-name self) (zk_variable-name other))
-)
-
-(define (zk_load self constant)
-    (fprintf out "load ~a ~a\n" (zk_variable-name self) constant)
-)
-
-(define (zk_lc0_add self)
-    (fprintf out "lc0_add ~a\n" (zk_variable-name self)))
-(define (zk_lc1_add self)
-    (fprintf out "lc1_add ~a\n" (zk_variable-name self)))
-(define (zk_lc2_add self)
-    (fprintf out "lc2_add ~a\n" (zk_variable-name self)))
-(define (zk_lc0_sub self)
-    (fprintf out "lc0_sub ~a\n" (zk_variable-name self)))
-(define (zk_lc1_sub self)
-    (fprintf out "lc1_sub ~a\n" (zk_variable-name self)))
-(define (zk_lc2_sub self)
-    (fprintf out "lc2_sub ~a\n" (zk_variable-name self)))
-(define (zk_lc0_add_coeff constant self)
-    (fprintf out "lc0_add_coeff ~a ~a\n" constant (zk_variable-name self)))
-(define (zk_lc1_add_coeff constant self)
-    (fprintf out "lc1_add_coeff ~a ~a\n" constant (zk_variable-name self)))
-(define (zk_lc2_add_coeff constant self)
-    (fprintf out "lc2_add_coeff ~a ~a\n" constant (zk_variable-name self)))
-(define (zk_lc0_add_one)
-    (fprintf out "lc0_add_one\n"))
-(define (zk_lc1_add_one)
-    (fprintf out "lc1_add_one\n"))
-(define (zk_lc2_add_one)
-    (fprintf out "lc2_add_one\n"))
-(define (zk_enforce)
-    (fprintf out "enforce\n")
-)
-
-