+ if (symbol_p(cons->car)) {
+ if (strcmp(cons->car.atom->sym, "+") == 0) {
+ struct EvalResult args = eval_all_args(gc, scope, cons->cdr);
+ if (args.is_error) {
+ return args;
+ }
+ return plus_op(gc, args.expr);
+ } else if (strcmp(cons->car.atom->sym, "set") == 0) {
+ struct Expr args = cons->cdr;
+ struct EvalResult n = length(gc, args);
+
+ if (n.is_error) {
+ return n;
+ }
+
+ if (n.expr.atom->num != 2) {
+ return eval_failure(list(gc, 3,
+ SYMBOL(gc, "wrong-number-of-arguments"),
+ SYMBOL(gc, "set"),
+ NUMBER(gc, n.expr.atom->num)));
+ }
+
+ struct Expr name = args.cons->car;
+ if (!symbol_p(name)) {
+ return eval_failure(list(gc, 3,
+ SYMBOL(gc, "wrong-type-argument"),
+ SYMBOL(gc, "symbolp"),
+ name));
+ }
+
+ struct EvalResult value = eval(gc, scope, args.cons->cdr.cons->car);
+ if (value.is_error) {
+ return value;
+ }
+
+ set_scope_value(gc, scope, name, value.expr);
+
+ return eval_success(value.expr);
+ } else if (strcmp(cons->car.atom->sym, "quote") == 0) {
+ /* TODO: quote does not check the amout of it's arguments */
+ return eval_success(cons->cdr.cons->car);
+ } else if (strcmp(cons->car.atom->sym, "lambda") == 0) {
+ return eval_success(cons_as_expr(cons));
+ } else {
+ struct EvalResult r = eval_all_args(gc, scope, cons_as_expr(cons));
+
+ if (r.is_error) {
+ return r;
+ }
+
+ if (!callable_p(r.expr.cons->car)) {
+ return eval_failure(CONS(gc,
+ SYMBOL(gc, "not-callable"),
+ r.expr.cons->car));
+ }