-
Notifications
You must be signed in to change notification settings - Fork 0
/
eval.c
96 lines (94 loc) · 2.12 KB
/
eval.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <assert.h>
#include "eval.h"
#include "structure.h"
#include "symbol.h"
#include "macro.h"
#include "error.h"
#include "environment.h"
#include "builtin.h"
Node * apply(Node * ff, Node * args) {
if (ff->type != FIX_LAMBDA && ff->type != VAR_LAMBDA && ff->type != BUI_LAMBDA) {
printf("%d\n", ff->type);
error("not callable");
abort();
}
if (ff->type == BUI_LAMBDA) {
return callBuiltinLambda(ff, args);
}
LambdaNode * f = toLambda(ff);
unsigned int argsLen = length(f->formal);
unsigned int len = length(args);
if ((f->type == FIX_LAMBDA && argsLen != len) || argsLen > len) {
error("arguments mismatch");
abort();
}
Env * env = newEnv(toLambda(f)->env);
Node * fiter = f->formal;
Node * aiter = args;
while (fiter->type == LIST || fiter->type == PAIR) {
updateEnv(env, toSym(car(fiter))->sym, car(aiter));
fiter = cdr(fiter);
aiter = cdr(aiter);
}
if (f->type == VAR_LAMBDA) {
updateEnv(env, toSym(fiter)->sym, aiter);
}
Node * biter = f->body;
Node * last;
for (; biter->type == LIST; biter = cdr(biter)) {
last = eval(car(biter), env);
}
return last;
}
Node * eval(Node * expr, Env * env) {
if (expr == NULL) {
return NULL;
}
switch (expr->type) {
case SYMBOL:
return lookup(env, toSym(expr)->sym);
case PAIR:
error("cannot eval a pair");
abort();
break;
case LIST: {
Node * first = eval(car(expr), env);
if (first->type == MACRO || first->type == BUILTIN_MAC) {
Node * ret = transform(first, expr, env);
return eval(ret, env);
} else {
Node * args = ∅
Node ** last = &args;
for (Node * iter = cdr(expr); iter->type == LIST; iter = cdr(iter)) {
*last = cons(eval(car(iter), env), &empty);
last = &cdr(*last);
}
return apply(first, args);
}
}
case EMPTY:
error("cannot eval an empty list");
abort();
break;
case VECTOR:
case BOOL:
case COMPLEX:
case CHAR:
case STRING:
case FIX_LAMBDA:
case VAR_LAMBDA:
case MACRO:
case BUILTIN_MAC:
case BUI_LAMBDA:
case UNSPECIFIED:
return expr;
case DUMMY:
case LISTELL:
case VECTORELL:
case MARG:
assert(0);
break;
}
abort();
return NULL;
}