+ struct Expr expr = void_expr();
+ struct EvalResult result = match_list(gc, "e", args, &expr);
+ if (result.is_error) {
+ return result;
+ }
+
+ const char *unquote = NULL;
+ struct Expr unquote_expr = void_expr();
+ result = match_list(gc, "qe", expr, &unquote, &unquote_expr);
+
+ if (!result.is_error && strcmp(unquote, "unquote") == 0) {
+ return eval(gc, scope, unquote_expr);
+ } else if (cons_p(expr)) {
+ struct EvalResult left = quasiquote(param, gc, scope, CONS(gc, CAR(expr), NIL(gc)));
+ if (left.is_error) {
+ return left;
+ }
+ struct EvalResult right = quasiquote(param, gc, scope, CONS(gc, CDR(expr), NIL(gc)));
+ if (right.is_error) {
+ return right;
+ }
+ return eval_success(CONS(gc, left.expr, right.expr));
+ } else {
+ return eval_success(expr);
+ }
+}
+
+static struct EvalResult
+unquote(void *param, Gc *gc, struct Scope *scope, struct Expr args)
+{
+ (void) param;
+ trace_assert(gc);
+ trace_assert(scope);
+ (void) args;