5 #include "./builtins.h"
7 #include "./interpreter.h"
10 struct EvalResult eval_success(struct Expr expr)
12 struct EvalResult result = {
20 struct EvalResult eval_failure(struct Expr error)
22 struct EvalResult result = {
30 static struct EvalResult length(Gc *gc, struct Expr obj)
33 return eval_failure(list(gc, 3,
34 SYMBOL(gc, "wrong-argument-type"),
39 return eval_success(NUMBER(gc, length_of_list(obj)));
42 static struct EvalResult eval_atom(Gc *gc, struct Scope *scope, struct Atom *atom)
51 return eval_success(atom_as_expr(atom));
54 if (nil_p(atom_as_expr(atom))) {
55 return eval_success(atom_as_expr(atom));
58 struct Expr value = get_scope_value(scope, atom_as_expr(atom));
61 return eval_failure(CONS(gc,
62 SYMBOL(gc, "void-variable"),
66 return eval_success(value.cons->cdr);
70 return eval_failure(CONS(gc,
71 SYMBOL(gc, "unexpected-expression"),
75 static struct EvalResult eval_all_args(Gc *gc, struct Scope *scope, struct Expr args)
82 return eval_atom(gc, scope, args.atom);
85 struct EvalResult car = eval(gc, scope, args.cons->car);
90 struct EvalResult cdr = eval_all_args(gc, scope, args.cons->cdr);
95 return eval_success(cons_as_expr(create_cons(gc, car.expr, cdr.expr)));
101 return eval_failure(CONS(gc,
102 SYMBOL(gc, "unexpected-expression"),
106 static struct EvalResult plus_op(Gc *gc, struct Expr args)
108 long int result = 0.0f;
110 while (!nil_p(args)) {
111 if (args.type != EXPR_CONS) {
112 return eval_failure(CONS(gc,
113 SYMBOL(gc, "expected-cons"),
117 if (args.cons->car.type != EXPR_ATOM ||
118 args.cons->car.atom->type != ATOM_NUMBER) {
119 return eval_failure(CONS(gc,
120 SYMBOL(gc, "expected-number"),
124 result += args.cons->car.atom->num;
125 args = args.cons->cdr;
128 return eval_success(atom_as_expr(create_number_atom(gc, result)));
131 static struct EvalResult call_lambda(Gc *gc,
135 if (!lambda_p(lambda)) {
136 return eval_failure(CONS(gc,
137 SYMBOL(gc, "expected-callable"),
142 return eval_failure(CONS(gc,
143 SYMBOL(gc, "expected-list"),
147 struct Expr vars = lambda.cons->cdr.cons->car;
149 if (length_of_list(args) != length_of_list(vars)) {
150 return eval_failure(CONS(gc,
151 SYMBOL(gc, "wrong-number-of-arguments"),
152 NUMBER(gc, length_of_list(args))));
155 push_scope_frame(gc, scope, vars, args);
156 struct Expr body = lambda.cons->cdr.cons->cdr;
158 struct EvalResult result = eval_success(NIL(gc));
160 while (!nil_p(body)) {
161 result = eval(gc, scope, body.cons->car);
162 if (result.is_error) {
165 body = body.cons->cdr;
168 pop_scope_frame(gc, scope);
173 static struct EvalResult call_callable(Gc *gc,
175 struct Expr callable,
177 if (callable.type == EXPR_ATOM && callable.atom->type == ATOM_NATIVE) {
178 return ((NativeFunction)callable.atom->native.fun)(callable.atom->native.param, gc, scope, args);
181 return call_lambda(gc, scope, callable, args);
184 static struct EvalResult eval_funcall(Gc *gc, struct Scope *scope, struct Cons *cons)
189 if (symbol_p(cons->car)) {
190 if (strcmp(cons->car.atom->sym, "+") == 0) {
191 struct EvalResult args = eval_all_args(gc, scope, cons->cdr);
195 return plus_op(gc, args.expr);
196 } else if (strcmp(cons->car.atom->sym, "set") == 0) {
197 struct Expr args = cons->cdr;
198 struct EvalResult n = length(gc, args);
204 if (n.expr.atom->num != 2) {
205 return eval_failure(list(gc, 3,
206 SYMBOL(gc, "wrong-number-of-arguments"),
208 NUMBER(gc, n.expr.atom->num)));
211 struct Expr name = args.cons->car;
212 if (!symbol_p(name)) {
213 return eval_failure(list(gc, 3,
214 SYMBOL(gc, "wrong-type-argument"),
215 SYMBOL(gc, "symbolp"),
219 struct EvalResult value = eval(gc, scope, args.cons->cdr.cons->car);
220 if (value.is_error) {
224 set_scope_value(gc, scope, name, value.expr);
226 return eval_success(value.expr);
227 } else if (strcmp(cons->car.atom->sym, "quote") == 0) {
228 /* TODO(#334): quote does not check the amout of it's arguments */
229 return eval_success(cons->cdr.cons->car);
230 } else if (strcmp(cons->car.atom->sym, "lambda") == 0) {
231 /* TODO(#335): lambda special form doesn't check if it forms a callable object */
232 return eval_success(cons_as_expr(cons));
236 struct EvalResult r = eval_all_args(gc, scope, cons_as_expr(cons));
242 return call_callable(gc, scope, r.expr.cons->car, r.expr.cons->cdr);
245 struct EvalResult eval(Gc *gc, struct Scope *scope, struct Expr expr)
249 return eval_atom(gc, scope, expr.atom);
252 return eval_funcall(gc, scope, expr.cons);
257 return eval_failure(CONS(gc,
258 SYMBOL(gc, "unexpected-expression"),