+ struct Expr head = block;
+ struct EvalResult eval_result = eval_success(NIL(gc));
+
+ while (cons_p(head)) {
+ eval_result = eval(gc, scope, CAR(head));
+ if (eval_result.is_error) {
+ return eval_result;
+ }
+
+ head = CDR(head);
+ }
+
+ return eval_result;
+}
+
+struct EvalResult eval(Gc *gc, struct Scope *scope, struct Expr expr)
+{
+ switch(expr.type) {
+ case EXPR_ATOM:
+ return eval_atom(gc, scope, expr.atom);
+
+ case EXPR_CONS:
+ return call_callable(gc, scope, expr.cons->car, expr.cons->cdr);
+
+ default: {}
+ }
+
+ return eval_failure(CONS(gc,
+ SYMBOL(gc, "unexpected-expression"),
+ expr));
+}
+
+struct EvalResult
+car(void *param, Gc *gc, struct Scope *scope, struct Expr args)
+{
+ (void) param;
+ assert(gc);
+ assert(scope);
+
+ struct Expr xs = NIL(gc);
+
+ struct EvalResult result = match_list(gc, "e", args, &xs);
+ if (result.is_error) {
+ return result;
+ }
+
+ if (nil_p(xs)) {
+ return eval_success(xs);
+ }
+
+ if (!cons_p(xs)) {
+ return wrong_argument_type(gc, "consp", xs);
+ }