-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathobject.c
193 lines (148 loc) · 3.75 KB
/
object.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/* Object model.
*
* Copyright (c) 2010 James E. Ingram
* See the LICENSE file for terms of use.
*/
#include "gc.h"
#include "error.h"
#include "object.h"
#include "port.h"
#include "table.h"
extern int is_end_of_file(object *obj);
extern int is_number(object *obj);
extern int is_boolean(object *obj);
extern int is_true(object *obj);
extern int is_character(object *obj);
extern int is_string(object *obj);
extern int is_symbol(object *obj);
extern int is_empty_list(object *obj);
extern int is_pair(object *obj);
extern object *car(object *pair);
extern void set_car(object *pair, object *obj);
extern object *cdr(object *pair);
extern void set_cdr(object *pair, object *obj);
extern int is_primitive_proc(object *obj);
extern int is_compound_proc(object *obj);
extern int is_procedure(object *obj);
extern int is_port(object *obj);
extern int is_input_port(object *obj);
extern int is_output_port(object *obj);
static object *alloc_object(void);
static object end_of_file_object = { .type = END_OF_FILE };
static object empty_list = { .type = EMPTY_LIST };
static object true_object = { .type = BOOLEAN, .value.boolean = 1 };
static object false_object = { .type = BOOLEAN, .value.boolean = 0 };
static object *alloc_object(void)
{
object *obj = GC_MALLOC(sizeof(object));
if (obj == NULL) {
error("unable to allocate an object:");
}
return obj;
}
object *get_end_of_file(void)
{
return &end_of_file_object;
}
object *make_number(long value)
{
object *num = alloc_object();
num->type = NUMBER;
num->value.number = value;
return num;
}
object *get_boolean(int value)
{
return value == 0 ? &false_object : &true_object;
}
int is_false(object *obj)
{
return (obj->type == BOOLEAN && obj->value.boolean == 0);
}
object *make_character(char value)
{
object *c = alloc_object();
c->type = CHARACTER;
c->value.character = value;
return c;
}
object *make_string(char *value)
{
object *s = alloc_object();
s->type = STRING;
s->value.string = value;
return s;
}
object *get_empty_list(void)
{
return &empty_list;
}
object *cons(object *obj_car, object *obj_cdr)
{
object *p = alloc_object();
p->type = PAIR;
p->value.pair.car = obj_car;
p->value.pair.cdr = obj_cdr;
return p;
}
int is_list(object *obj)
{
if (is_empty_list(obj)) {
return 1;
}
while (is_pair(obj)) {
if (is_empty_list(cdr(obj))) {
return 1;
}
obj = cdr(obj);
}
return 0;
}
object *make_symbol(char const *name)
{
object *sym = lookup_symbol(name);
if (sym == NULL) {
sym = alloc_object();
sym->type = SYMBOL;
sym->value.symbol = name;
return insert_symbol(sym);
} else {
return sym;
}
}
object *make_primitive_proc(object *(*fn)(object *args))
{
object *prim = alloc_object();
prim->type = PRIMITIVE_PROC;
prim->value.primitive_proc = fn;
return prim;
}
object *make_compound_proc(object *parameters, object *body, object *env)
{
object *proc = alloc_object();
proc->type = COMPOUND_PROC;
proc->value.compound_proc.parameters = parameters;
proc->value.compound_proc.body = body;
proc->value.compound_proc.env = env;
return proc;
}
object *make_input_port(char const *file)
{
object *ip = alloc_object();
ip->type = PORT;
ip->value.port.mode = 0;
ip->value.port.state = 0;
open_port(ip, file);
// We should register a finalizer to close this file handle.
return ip;
}
object *make_output_port(char const *file)
{
object *op = alloc_object();
op->type = PORT;
op->value.port.mode = 1;
op->value.port.state = 0;
open_port(op, file);
// We should register a finalizer to close this file handle.
return op;
}