lisp_eval = (e, a) => {
  console.log('eval =>', pp(e), pp(a))
  let retval =
    atom(e) ? cdr(assoc(e, a)) :
    atom(car(e)) ? (
      eq(car(e), 'QUOTE') ? cadr(e) :
      eq(car(e), 'COND') ? evcon(cdr(e), a) :
      /* T ? */ lisp_apply(car(e), evlis(cdr(e), a), a)
    ) :
    /* T ? */ lisp_apply(car(e), evlis(cdr(e), a), a)
  console.log('eval <=', pp(retval))
  return retval
}

cadar = l => car(cdr(car(l)))

evcon = (c, a) => {
  console.log('evcon ==>', pp(c), pp(a))
  let retval = lisp_eval(caar(c), a) ? lisp_eval(cadar(c), a) :
  /* T ? */ evcon(cdr(c), a)
  console.log('evcon <==', pp(retval))
  return retval
}
evlis = (m, a) => {
  console.log('evlis ==>', pp(m), pp(a))
  let retval = nil(m) ? 'NIL' : cons(lisp_eval(car(m), a), evlis(cdr(m), a))
  console.log('evlis <==', pp(retval))
  return retval
}
