]> git.lizzy.rs Git - nothing.git/blob - src/script/interpreter.c
990df360ce6188d1aa5ced1fb3bd36db477bd2af
[nothing.git] / src / script / interpreter.c
1 #include <assert.h>
2 #include <math.h>
3 #include <string.h>
4
5 #include "./builtins.h"
6 #include "./expr.h"
7 #include "./interpreter.h"
8
9 struct EvalResult eval_success(struct Expr expr)
10 {
11     struct EvalResult result = {
12         .is_error = false,
13         .expr = expr,
14         .error = NULL
15     };
16
17     return result;
18 }
19
20 struct EvalResult eval_failure(const char *error, struct Expr expr)
21 {
22     struct EvalResult result = {
23         .is_error = true,
24         .error = error,
25         .expr = expr
26     };
27
28     return result;
29 }
30
31 static struct EvalResult eval_atom(struct Expr scope, struct Atom *atom)
32 {
33     /* TODO: eval_atom is not implemented */
34     assert(atom);
35     (void) scope;
36     return eval_failure("not implemented", void_expr());
37 }
38
39 static struct EvalResult eval_args(struct Expr scope, struct Expr args)
40 {
41     (void) scope;
42     (void) args;
43
44     switch(args.type) {
45     case EXPR_ATOM:
46         return eval_atom(scope, args.atom);
47
48     case EXPR_CONS: {
49         struct EvalResult car = eval(scope, args.cons->car);
50         if (car.is_error) {
51             return car;
52         }
53
54         struct EvalResult cdr = eval_args(scope, args.cons->cdr);
55         if (cdr.is_error) {
56             return cdr;
57         }
58
59         /* TODO: memory leak */
60         return eval_success(cons_as_expr(create_cons(car.expr, cdr.expr)));
61     }
62
63     default: {}
64     }
65
66     return eval_failure("Unexpected expression", args);
67 }
68
69 static struct EvalResult plus_op(struct Expr args)
70 {
71     float result = 0.0f;
72
73     while (!nil_p(args)) {
74         if (args.type != EXPR_CONS) {
75             return eval_failure("Expected cons", args);
76         }
77
78         if (args.cons->car.type != EXPR_ATOM ||
79             args.cons->car.atom->type != ATOM_NUMBER) {
80             return eval_failure("Expected number", args.cons->car);
81         }
82
83         result += args.cons->car.atom->num;
84         args = args.cons->cdr;
85     }
86
87     return eval_success(atom_as_expr(create_number_atom(result)));
88 }
89
90 static struct EvalResult eval_funcall(struct Expr scope, struct Cons *cons)
91 {
92     assert(cons);
93     (void) scope;
94
95     if (cons->car.type != EXPR_ATOM && cons->car.atom->type != ATOM_SYMBOL) {
96         return eval_failure("Not a function", cons->car);
97     }
98
99     if (strcmp(cons->car.atom->sym, "+")) {
100         struct EvalResult args = eval_args(scope, cons->cdr);
101         if (args.is_error) {
102             return args;
103         }
104         return plus_op(args.expr);
105     }
106
107     return eval_failure("Unknown function", cons->car);
108 }
109
110 struct EvalResult eval(struct Expr scope, struct Expr expr)
111 {
112     switch(expr.type) {
113     case EXPR_ATOM:
114         return eval_atom(scope, expr.atom);
115
116     case EXPR_CONS:
117         return eval_funcall(scope, expr.cons);
118
119     default: {}
120     }
121
122     return eval_failure("Unexpected expression", expr);
123 }