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
97
98
|
#include "value.h"
#define PROCEDURES(X) \
/* X(symbol, name, argc) */ \
X(plus, "+", 2) \
X(minus, "-", 2) \
X(cons, "cons", 2) \
X(car, "car", 1) \
X(cdr, "cdr", 1) \
// Number of builtin procedures
#define PLUS_ONE(_symbol, _name, _argc) 1 +
#define BUILTIN_PROCEDURES PROCEDURES(PLUS_ONE) 0
// Forward decalration of the procedures
#define DECLARE_PROCEDURE(proc) value_t proc(value_t *args)
#define FORWARD_DECLARATION(symbol, _name, _argc) \
DECLARE_PROCEDURE(symbol);
PROCEDURES(FORWARD_DECLARATION)
// Fill procedure struct for the value_t
#define PROC_DESCRIPTION(symbol, _name, argc) \
{argc, symbol},
struct proc_builtin builtin_proc_descriptions[] = {
PROCEDURES(PROC_DESCRIPTION)
};
// List of ordered names of procedures
#define PROC_NAME(symbol, name, _argc) \
name,
const char *builtin_proc_name_list[] = {
PROCEDURES(PROC_NAME)
};
// ----- Definitions -----
#define ASSERT_TYPE(proc, args, pos, vtype, fail) \
if(args[pos]->type != vtype) { \
err("Expected arg %d of %s to be %s instead of %s", \
pos, #proc, "", ""); \
fail; \
}
#define PROC_ASSERT_TYPE(pos, vtype, fail) \
ASSERT_TYPE(P, args, pos, vtype, fail)
#define P plus
DECLARE_PROCEDURE(P)
{
PROC_ASSERT_TYPE(0, VALUE_INT, return VALUE_EMPTY);
PROC_ASSERT_TYPE(1, VALUE_INT, return VALUE_EMPTY);
int sum = args[0]->value.num + args[1]->value.num;
return value_create(VALUE_INT, &sum);
}
#undef P
#define P minus
DECLARE_PROCEDURE(P)
{
PROC_ASSERT_TYPE(0, VALUE_INT, return VALUE_EMPTY);
PROC_ASSERT_TYPE(1, VALUE_INT, return VALUE_EMPTY);
int difference = args[0]->value.num - args[1]->value.num;
return value_create(VALUE_INT, &difference);
}
#undef P
#define P cons
DECLARE_PROCEDURE(P)
{
struct cons cons = {value_copy(args[0]), value_copy(args[1])};
return value_create(VALUE_CONS, &cons);
}
#undef P
#define P car
DECLARE_PROCEDURE(P)
{
PROC_ASSERT_TYPE(0, VALUE_CONS, return VALUE_EMPTY);
value_t left = value_copy(args[0]->value.cons.left);
return left;
}
#undef P
#define P cdr
DECLARE_PROCEDURE(P)
{
PROC_ASSERT_TYPE(0, VALUE_CONS, return VALUE_EMPTY);
value_t right = value_copy(args[0]->value.cons.right);
return right;
}
#undef P
|