Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
#include
#include
#include
#include
#include
#include
<stdio.h>
<string.h>
<signal.h>
<stdarg.h>
<stdlib.h>
<sys/types.h>
<assert.h>
int type;
struct GC_StackRoot
{
void **root;
struct GC_StackRoot *next;
#if !defined(NDEBUG)
int
live;
const char *name;
const char *file;
long line;
#endif
};
#if defined(NDEBUG)
# define GC_PROTECT(V)
struct GC_StackRoot _sr_##V; _sr_##V.root= (voi
d *)&V; GC_push_root(&_sr_##V)
# define GC_UNPROTECT(V)
GC_pop_root(&_sr_##V)
#else
# define GC_PROTECT(V)
struct GC_StackRoot _sr_##V; _sr_##V.root= (voi
d *)&V; GC_push_root(&_sr_##V, #V, __FILE__, __LINE__)
# define GC_UNPROTECT(V)
GC_pop_root(&_sr_##V, #V, __FILE__, __LINE__)
#endif
#define GC_INIT()
#define GC_init()
#if !defined(GC_API)
# define GC_API
#endif
GC_API
GC_API
GC_API
GC_API
GC_API
GC_API
GC_API
GC_API
GC_API
GC_API
GC_API
GC_API
GC_API
GC_API
void
void
void
void
size_t
void
void
void
void
void
void
size_t
size_t
double
GC_API int
*GC_malloc(size_t nbytes);
*GC_malloc_atomic(size_t nbytes);
*GC_realloc(void *ptr, size_t lbs);
GC_free(void *ptr);
GC_size(void *ptr);
GC_add_root(void *root);
GC_delete_root(void *root);
GC_mark(void *ptr);
GC_mark_leaf(void *ptr);
GC_sweep(void);
GC_gcollect(void);
GC_count_objects(void);
GC_count_bytes(void);
GC_count_fragments(void);
GC_atomic(void *ptr);
#ifndef NDEBUG
GC_API void
*GC_check(void *ptr);
GC_API void
*GC_stamp(void *ptr, const char *file, long line, const char
*func);
GC_API const char *GC_file(void *ptr);
GC_API long
GC_line(void *ptr);
GC_API const char *GC_function(void *ptr);
#else
# define GC_check(PTR)
(PTR)
# define GC_stamp(PTR, FILE, LINE, FUNC)
(PTR)
# define GC_file(PTR)
"?"
# define GC_line(PTR)
0
# define GC_function(PTR)
"?"
#endif
typedef void (*GC_finaliser_t)(void *ptr, void *data);
GC_API void GC_register_finaliser(void *ptr, GC_finaliser_t finaliser, void *da
ta);
extern struct GC_StackRoot *GC_stack_roots;
#if defined(NDEBUG)
GC_API inline void GC_push_root(struct GC_StackRoot *sr)
{
sr->next= GC_stack_roots;
GC_stack_roots= sr;
}
GC_API inline void GC_pop_root(struct GC_StackRoot *sr)
{
# if 0
GC_stack_roots= sr->next;
# else /* paranoid version for broken code warns of mismatched pops with a SEGV
*/
struct GC_StackRoot *nr= sr->next;
while (nr != GC_stack_roots) GC_stack_roots= GC_stack_roots->next;
# endif
}
#else
GC_API inline void GC_push_root(struct GC_StackRoot *sr, const char *name, con
st char *file, int line)
{
sr->next= GC_stack_roots;
sr->name= name;
sr->file= file;
sr->line= line;
sr->live= 1;
GC_stack_roots= sr;
}
static int GC_roots_include(struct GC_StackRoot *roots, struct GC_StackRoot *r
oot)
{
while (roots) {
if (roots == root) return 1;
roots= roots->next;
}
return 0;
}
GC_API inline void GC_pop_root(struct GC_StackRoot *sr, const char *name, cons
t char *file, int line)
{
struct GC_StackRoot *nr= sr->next;
struct GC_StackRoot *gr= GC_stack_roots;
if (!sr->live)
{ fprintf(stderr, "*** %s %d %s: STALE P
OP IN GC_pop_root\n", file, line, name); goto die; }
sr->live= 0;
if (GC_roots_include(nr, sr))
{ fprintf(stderr, "*** %s %d %s: CYCLE I
N GC_pop_root\n", file, line, name); goto die; }
int n= 0;
while (nr != gr) {
if (n++ > 10) { fprintf(stderr, "*** %s %d %s: LOOP IN GC_pop_root\n", fil
e, line, name); goto die; }
gr= gr->next;
}
GC_stack_roots= gr;
return;
die:
fprintf(stderr, "* gc stack roots = %p %s %ld %s\n", gr, gr->file, gr->line,
gr->name);
fprintf(stderr, "* popped root
= %p %s %ld %s\n", sr, sr->file, sr->line,
sr->name);
while (nr) {
fprintf(stderr, "* next root
= %p %s %ld %s\n", nr, nr ? nr->file : 0
, nr ? nr->line : 0, nr ? nr->name : 0);
nr= nr->next;
}
abort();
}
#endif
typedef void (*GC_pre_mark_function_t)(void);
extern GC_pre_mark_function_t GC_pre_mark_function;
typedef void (*GC_mark_function_t)(void *ptr);
extern GC_mark_function_t GC_mark_function;
typedef void (*GC_free_function_t)(void *ptr);
extern GC_free_function_t GC_free_function;
#define GC_ALIGN
#define GC_MEMORY
#define GC_QUANTUM
#if defined(DEBUGGC)
# define ALLOCS_PER_GC
#else
# define ALLOCS_PER_GC
#endif
sizeof(long)
0x7fffffff
50*1024
1
#define VERBOSE
#define BITS_PER_WORD
(sizeof(long) * 8)
32768
__attribute__((__packed_
__attribute__((__packed_
__attribute__((__packed_
#ifndef NDEBUG
GC_API void *GC_stamp(void *ptr, const char *file, long line, const char *func)
{
gcheader *hdr= ptr2hdr(ptr);
hdr->file= file;
hdr->line= line;
hdr->func= func;
return ptr;
}
GC_API const char *GC_file(void *ptr)
GC_API long
GC_line(void *ptr)
GC_API const char *GC_function(void *ptr)
#endif
typedef struct _gcfinaliser
{
void
*ptr;
GC_finaliser_t
finaliser;
void
*data;
struct _gcfinaliser *next;
} gcfinaliser;
static gcheader gcbase= { 0, { -1 }, &gcbase };
static gcheader *gcnext= &gcbase;
static size_t
static int
static int
gcQuantum= GC_QUANTUM;
gcCount= ALLOCS_PER_GC;
gcAllocs= ALLOCS_PER_GC;
{ return ptr2hdr(ptr)->file; }
{ return ptr2hdr(ptr)->line; }
{ return ptr2hdr(ptr)->func; }
static size_t
gcMemory= GC_MEMORY;
gcnext= hdr->next;
mem= hdr2ptr(hdr);
if VERBOSE > 2
//if ((long)hdr == 0x800248) abort();
fprintf(stderr, "MALLOC %p -> %p + %i\n", mem, hdr, (int)GC_size(mem))
;
#
endif
memset(mem, 0, hdr->size);
gcMemory -= hdr->size;
//if (mem == (void *)0x617190) { fprintf(stderr, "ALLOCATING %p\n", me
m); bkpt(); }
return mem;
}
}
hdr= hdr->next;
} while (hdr != org);
{
size_t incr= gcQuantum;
size_t req= sizeof(gcheader) + lbs;
while (incr <= req) incr *= 2;
//fprintf(stderr, "extending by %ld => %ld @ %d\n", req, incr, (int)(gcCount
- gcAllocs));
hdr= (gcheader *)malloc(incr);
//fprintf(stderr, "buffer at %x\n", (int)hdr);
if (hdr != (gcheader *)-1)
{
hdr->flags= 0;
hdr->next= gcbase.next;
gcbase.next= hdr;
hdr->size= incr - sizeof(gcheader);
#if VERBOSE
fprintf(stderr, "extend by %i at %p\n", (int)hdr->size, hdr);
#endif
goto again;
}
fprintf(stderr, "GC: sbrk failed\n");
}
full:
fprintf(stderr, "GC: out of memory\n");
abort();
return 0;
}
GC_API void *GC_malloc_atomic(size_t lbs)
{
void *mem= GC_malloc(lbs);
ptr2hdr(mem)->atom= 1;
return mem;
}
GC_API void *GC_realloc(void *ptr, size_t lbs)
{
gcheader *hdr= ptr2hdr(ptr);
void *mem;
if (lbs <= hdr->size) return ptr;
mem= GC_malloc(lbs);
memcpy(mem, ptr, hdr->size);
ptr2hdr(mem)->atom= hdr->atom;
GC_free(ptr);
return mem;
}
static gcheader *GC_freeHeader(gcheader *hdr)
{
#if VERBOSE > 2
fprintf(stderr, "FREE %p -> %p %s:%ld %s\n", hdr2ptr(hdr), hdr, hdr->file, hdr
->line, hdr->func);
if (hdr->line == 0) {
fflush(stdout);
abort();
}
#endif
hdr->flags= 0;
gcMemory += hdr->size;
return hdr;
}
GC_API void GC_free(void *ptr)
{
gcnext= GC_freeHeader(ptr2hdr(ptr));
}
GC_API size_t GC_size(void *ptr)
{
return ptr2hdr(ptr)->size;
}
GC_API void GC_default_pre_mark_function(void) {}
GC_pre_mark_function_t GC_pre_mark_function= GC_default_pre_mark_function;
GC_API void GC_default_mark_function(void *ptr)
{
gcheader *hdr= ptr2hdr(ptr);
void
**pos= ptr;
void
**lim= hdr2ptr(hdr) + hdr->size - sizeof(void *);
while (pos <= lim)
{
void *field= *pos;
if (field && !((long)field & 1))
GC_mark(field);
++pos;
}
}
GC_mark_function_t GC_mark_function= GC_default_mark_function;
GC_API void GC_mark(void *ptr)
{
if ((long)ptr & 1) return;
gcheader *hdr= ptr2hdr(ptr);
#if VERBOSE > 3
fprintf(stderr, "mark? %p -> %p used %d atom %d mark %d\n", ptr, hdr, hdr->use
d, hdr->atom, hdr->mark);
#endif
if (!hdr->mark) {
hdr->mark= 1;
if (!hdr->atom)
GC_mark_function(ptr);
}
}
GC_API void GC_mark_leaf(void *ptr)
{
ptr2hdr(ptr)->mark= 1;
}
GC_free_function_t GC_free_function= 0;
GC_API void GC_sweep(void)
{
gcheader *hdr= gcbase.next;
do {
#if VERBOSE > 3
fprintf(stderr, "sweep? %p %d\n", hdr, hdr->flags);
#endif
if (hdr->flags)
{
if (hdr->mark)
hdr->mark= 0;
else {
if (hdr->finalisers) {
while (hdr->finalisers) {
gcfinaliser *gcf= hdr->finalisers;
hdr->finalisers= gcf->next;
gcf->next= finalisable;
finalisable= gcf;
}
}
else {
if (GC_free_function) GC_free_function(hdr2ptr(hdr));
hdr= GC_freeHeader(hdr);
}
}
}
hdr= hdr->next;
} while (hdr != &gcbase);
gcnext= gcbase.next;
while (finalisable)
{
gcfinaliser *gcf= finalisable;
gcf->finaliser(gcf->ptr, gcf->data);
finalisable= gcf->next;
free(gcf);
}
}
static void ***roots= 0;
static size_t numRoots= 0;
static size_t maxRoots= 0;
struct GC_StackRoot *GC_stack_roots= 0;
GC_API void GC_add_root(void *root)
{
if (numRoots == maxRoots)
roots= maxRoots
? realloc(roots, sizeof(roots[0]) * (maxRoots *= 2))
: malloc (
sizeof(roots[0]) * (maxRoots= 128));
roots[numRoots++]= (void **)root;
assert(root);
}
GC_API void GC_delete_root(void *root)
{
int i;
for (i= 0; i < numRoots; ++i)
if (roots[i] == (void **)root)
break;
if (i < numRoots)
{
memmove(roots + i, roots + i + 1, sizeof(roots[0]) * (numRoots - i));
--numRoots;
}
}
GC_API long GC_collections= 0;
GC_API void GC_gcollect(void)
{
int i;
struct GC_StackRoot *sr;
++GC_collections;
#if !defined(NDEBUG)
{
# undef static
static char *cursors= "-/|\\";
static int cursor= 0;
if (GC_collections % 100 == 0) {
if (0 == cursors[cursor]) cursor= 0;
fprintf(stderr, "%c\010", cursors[cursor]);
++cursor;
}
# if (NONSTATIC)
#
define static
# endif
}
#endif
GC_pre_mark_function();
#if VERBOSE >= 1
fprintf(stderr, "*** GC: mark roots\n");
#endif
for (i= 0; i < numRoots; ++i)
if (*roots[i]) {
#
if VERBOSE >= 2
fprintf(stderr, "*** GC: root %i *%p -> %p\n", i, roots[i], *roots[i]);
#
endif
GC_mark(*roots[i]);
}
#if VERBOSE > 0
fprintf(stderr, "*** GC: mark stack\n");
#endif
for (sr= GC_stack_roots; sr; sr= sr->next) {
#if VERBOSE > 2 && defined(DEBUGGC)
fprintf(stderr, "*** GC: stack root %p %s %s:%ld\n", *sr->root, sr->name, sr
->file, sr->line);
#endif
if (*(sr->root)) GC_mark(*(sr->root));
}
#if VERBOSE > 0
#ifndef NDEBUG
GC_API void *GC_check(void *ptr)
{
gcheader *hdr= ptr2hdr(ptr);
if (!hdr->used) {
hdr->used= 1;
printf("accessible dead object %p %s:%ld %s\n", ptr, hdr->file, hdr->line, h
dr->func);
}
return ptr;
}
#endif
GC_API void GC_register_finaliser(void *ptr, GC_finaliser_t finaliser, void *dat
a)
{
gcheader
*gch = ptr2hdr(ptr);
gcfinaliser *gcf = (struct _gcfinaliser *)malloc(sizeof(struct _gcfinaliser));
gcf->ptr
= ptr;
gcf->finaliser = finaliser;
gcf->data
= data;
gcf->next
= gch->finalisers;
gch->finalisers = gcf;
}
struct buffer
{
char *buffer;
int
size;
int
position;
};
#define BUFFER_INITIALISER { 0, 0, 0 }
static void buffer_reset(struct buffer *b)
{ b->position= 0; }
Long
String
Symbol
Pair
Array
Expr
Form
Fixed
Subr
union Object {
struct Long
struct String
struct Symbol
struct Pair
struct Array
struct Expr
struct Form
struct Fixed
struct Subr
};
{
{
{
{
{
{
{
{
{
long bits; };
oop size; char *bits; };
char *bits; };
oop head, tail; };
oop _array; };
oop defn, env; };
oop function; };
oop function; };
imp_t imp; char *name; };
Long;
String;
Symbol;
Pair;
Array;
Expr;
Form;
Fixed;
Subr;
(ptr2hdr(OBJ)->type= (TYPE))
#if defined(NDEBUG)
# define checkType(OBJ, TYPE) OBJ
#else
# define checkType(OBJ, TYPE) _checkType(OBJ, TYPE, #TYPE, __FILE__, __LINE__)
static inline oop _checkType(oop obj, int type, char *name, char *file, int li
ne)
{
if (obj && !ptr2hdr(obj)->used)
fatal("%s:%i: attempt to access dead obj
ect %s\n", file, line, name);
if (!is(type, obj))
fatal("%s:%i: typecheck failed for %s (%
i != %i)\n", file, line, name, type, getType(obj));
return obj;
}
#endif
#define get(OBJ, TYPE, FIELD)
#define set(OBJ, TYPE, FIELD, VALUE)
E))
(checkType(OBJ, TYPE)->TYPE.FIELD)
(checkType(OBJ, TYPE)->TYPE.FIELD= (VALU
#define getHead(OBJ)
#define getTail(OBJ)
get(OBJ, Pair,head)
get(OBJ, Pair,tail)
get((X), Long,bits)
{
{
{
{
{
{
{
#define newBits(TYPE)
#define newOops(TYPE)
car(car(obj)); }
car(cdr(obj)); }
cdr(cdr(obj)); }
car(car(car(obj))); }
car(cdr(car(obj))); }
car(cdr(cdr(obj))); }
car(cdr(cdr(cdr(obj)))); }
set(obj,
GC_PROTECT(gstr);
/* + 1 t
GC_PROTECT(obj);
GC_UNPROTECT(obj);
GC_UNPROTECT(gstr);
set(obj,
set(obj,
GC_PROTECT(elts);
GC_UNPROTECT(elts);
CHAR_PRINT
CHAR_BLANK
CHAR_ALPHA
CHAR_DIGIT10
CHAR_DIGIT16
CHAR_LETTER
(1<<0)
(1<<1)
(1<<2)
(1<<3)
(1<<4)
(1<<5)
set(obj,
set(obj,
set(obj,
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
09
0a
0b
0c
0d
0e
0f
10
11
12
13
14
15
16
17
18
19
1a
1b
1c
1d
1e
1f
20
21
22
23
24
25
26
27
28
29
2a
2b
2c
2d
2e
2f
30
31
32
33
34
35
36
37
38
39
3a
3b
3c
3d
3e
3f
40
41
42
43
44
ht
nl
vt
np
cr
so
si
dle
dc1
dc2
dc3
dc4
nak
syn
etb
can
em
sub
esc
fs
gs
rs
us
sp
!
"
#
$
%
&
'
(
)
*
+
,
.
/
0
1
2
3
4
5
6
7
8
9
:
;
<
=
>
?
@
A
B
C
D
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
0,
CHAR_PRINT |
0,
CHAR_PRINT |
CHAR_PRINT |
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT,
CHAR_PRINT,
CHAR_PRINT,
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT,
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_BLANK,
CHAR_BLANK,
CHAR_BLANK,
CHAR_BLANK,
CHAR_LETTER,
CHAR_PRINT,
CHAR_LETTER,
CHAR_LETTER,
CHAR_LETTER,
CHAR_LETTER,
CHAR_LETTER,
CHAR_LETTER,
CHAR_LETTER,
CHAR_LETTER,
CHAR_LETTER,
CHAR_LETTER,
CHAR_DIGIT10
CHAR_DIGIT10
CHAR_DIGIT10
CHAR_DIGIT10
CHAR_DIGIT10
CHAR_DIGIT10
CHAR_DIGIT10
CHAR_DIGIT10
CHAR_DIGIT10
CHAR_DIGIT10
CHAR_LETTER,
CHAR_LETTER,
CHAR_LETTER,
CHAR_LETTER,
CHAR_LETTER,
CHAR_LETTER,
CHAR_LETTER |
CHAR_LETTER |
CHAR_LETTER |
CHAR_LETTER |
|
|
|
|
|
|
|
|
|
|
CHAR_DIGIT16,
CHAR_DIGIT16,
CHAR_DIGIT16,
CHAR_DIGIT16,
CHAR_DIGIT16,
CHAR_DIGIT16,
CHAR_DIGIT16,
CHAR_DIGIT16,
CHAR_DIGIT16,
CHAR_DIGIT16,
CHAR_ALPHA
CHAR_ALPHA
CHAR_ALPHA
CHAR_ALPHA
|
|
|
|
CHAR_DIGIT16,
CHAR_DIGIT16,
CHAR_DIGIT16,
CHAR_DIGIT16,
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
};
45
46
47
48
49
4a
4b
4c
4d
4e
4f
50
51
52
53
54
55
56
57
58
59
5a
5b
5c
5d
5e
5f
60
61
62
63
64
65
66
67
68
69
6a
6b
6c
6d
6e
6f
70
71
72
73
74
75
76
77
78
79
7a
7b
7c
7d
7e
7f
E */
F */
G */
H */
I */
J */
K */
L */
M */
N */
O */
P */
Q */
R */
S */
T */
U */
V */
W */
X */
Y */
Z */
[ */
\ */
] */
^ */
_ */
` */
a */
b */
c */
d */
e */
f */
g */
h */
i */
j */
k */
l */
m */
n */
o */
p */
q */
r */
s */
t */
u */
v */
w */
x */
y */
z */
{ */
| */
} */
~ */
del */
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT,
CHAR_PRINT |
CHAR_PRINT,
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT,
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT |
CHAR_PRINT,
CHAR_PRINT |
CHAR_PRINT,
CHAR_PRINT |
0,
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CHAR_ALPHA | CHAR_DIGIT16,
CHAR_ALPHA | CHAR_DIGIT16,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_LETTER,
CHAR_LETTER,
CHAR_LETTER,
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
CHAR_LETTER
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CHAR_LETTER,
CHAR_LETTER,
CHAR_ALPHA |
CHAR_ALPHA |
CHAR_ALPHA |
CHAR_ALPHA |
CHAR_ALPHA |
CHAR_ALPHA |
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_ALPHA,
CHAR_DIGIT16,
CHAR_DIGIT16,
CHAR_DIGIT16,
CHAR_DIGIT16,
CHAR_DIGIT16,
CHAR_DIGIT16,
&
&
&
}
static oop read(FILE *fp)
{
for (;;) {
int c= getc(fp);
switch (c) {
case EOF: {
return (oop)EOF;
}
case '\t': case '\n': case '\r': case ' ' : {
continue;
}
case ';': {
for (;;) {
c= getc(fp);
if ('\n' == c || '\r' == c || EOF == c) break;
}
continue;
}
case '"': {
static struct buffer buf= BUFFER_INITIALISER;
buffer_reset(&buf);
for (;;) {
c= getc(fp);
if ('"' == c) break;
c= readChar(c, fp);
if (EOF == c)
fatal("EOF in string literal");
buffer_append(&buf, c);
}
oop obj= newString(buffer_contents(&buf));
//buffer_free(&buf);
return obj;
}
case '?': {
return newLong(readChar(getc(fp), fp));
}
case '\'': {
oop obj= read(fp);
GC_PROTECT(obj);
obj= newPair(obj, nil);
obj= newPair(s_quote, obj);
GC_UNPROTECT(obj);
return obj;
}
case '`': {
oop obj= read(fp);
GC_PROTECT(obj);
obj= newPair(obj, nil);
obj= newPair(s_quasiquote, obj);
GC_UNPROTECT(obj);
return obj;
}
case ',': {
oop sym= s_unquote;
c= getc(fp);
if ('@' == c) sym= s_unquote_splicing;
else
ungetc(c, fp);
oop obj= read(fp);
GC_PROTECT(obj);
}
if (obj == globals) {
fprintf(stream, "<globals>");
return;
}
switch (getType(obj)) {
case Undefined:
fprintf(stream, "UNDEFINED");
case Long:
fprintf(stream, "%ld", get(obj, Long,bits));
case String: {
if (!storing)
fprintf(stream, "%s", get(obj, String,bits));
else {
char *p= get(obj, String,bits);
int c;
putc('"', stream);
while ((c= *p++)) {
if (c >= ' ' && c < 127)
switch (c) {
case '"': printf("\\\""); break;
case '\\': printf("\\\\"); break;
default: putc(c, stream); break;
}
else fprintf(stream, "\\%03o", c);
}
putc('"', stream);
}
break;
}
case Symbol:
fprintf(stream, "%s", get(obj, Symbol,bits));
case Pair: {
fprintf(stream, "(");
for (;;) {
if (obj == globals) {
fprintf(stream, "<globals>");
break;
}
doprint(stream, getHead(obj), storing);
obj= getTail(obj);
if (!is(Pair, obj)) break;
fprintf(stream, " ");
}
if (nil != obj) {
fprintf(stream, " . ");
doprint(stream, obj, storing);
}
fprintf(stream, ")");
break;
}
case Array: {
int i, len= arrayLength(obj);
fprintf(stream, "Array(");
for (i= 0; i < len; ++i) {
if (i) fprintf(stream, " ");
doprint(stream, arrayAt(obj, i), storing);
}
fprintf(stream, ")");
break;
}
case Expr: {
fprintf(stream, "Expr(");
break;
break;
break;
{ fdumpln(stdout, obj); }
GC_PROTECT(tail);
GC_UNPROTECT(tail);
{
if (!is(Pair, list)) return list;
oop head= expand(getHead(list), env);
oop tail= exlist(getTail(list), env);
head= newPair(head, tail);
T(head);
return head;
}
GC_PROTECT(head);
GC_PROTECT(tail);
GC_UNPROTECT(tail); GC_UNPROTEC
GC_UNPROTECT(args);
}
}
return expr;
}
static oop enlist(oop list, oop env)
{
if (!is(Pair, list)) return list;
oop head= encode(getHead(list), env);
oop tail= enlist(getTail(list), env);
head= newPair(head, tail);
T(head);
return head;
}
GC_PROTECT(head);
GC_PROTECT(tail);
GC_UNPROTECT(tail); GC_UNPROTEC
GC_PROTECT(args);
GC_UNPROTECT(args);
}
static oop eval(oop obj, oop env)
{
if (opt_v > 1) { printf("EVAL "); dumpln(obj); }
arrayAtPut(traceStack, traceDepth++, obj);
oop ev= arrayAt(getTail(evaluators), getType(obj));
if (nil != ev) {
oop args= newPair(obj, nil);
GC_PROTECT(args);
obj= apply(ev, args, env);
GC_UNPROTECT(args);
}
--traceDepth;
return obj;
}
static subr(if)
{
if (nil != eval(car(args), env))
return eval(cadr(args), env);
oop ans= nil;
args= cddr(args);
while (is(Pair, args)) {
ans= eval(getHead(args), env);
args= cdr(args);
}
return ans;
}
static subr(and)
{
oop ans= s_t;
for (; is(Pair, args); args= getTail(args))
if (nil == (ans= eval(getHead(args), env)))
break;
return ans;
}
static subr(or)
{
oop ans= nil;
for (; is(Pair, args); args= getTail(args))
if (nil != (ans= eval(getHead(args), env)))
break;
return ans;
}
static subr(set)
{
oop var= assq(car(args), env);
if (!is(Pair,var)) {
fprintf(stderr, "\nerror: cannot set undefined variable: ");
fdumpln(stderr, car(args));
fatal(0);
}
return setTail(var, eval(cadr(args), env));
}
static subr(let)
{
oop env2= env;
GC_PROTECT(env2);
oop tmp= nil;
GC_PROTECT(tmp);
oop bindings= car(args);
oop body= cdr(args);
while (is(Pair, bindings)) {
oop binding= getHead(bindings);
if (is(Pair, binding)) {
oop symbol= getHead(binding);
oop prog= getTail(binding);
while (is(Pair, prog)) {
oop value= getHead(prog);
tmp= eval(value, env);
prog= getTail(prog);
}
tmp= newPair(symbol, tmp);
env2= newPair(tmp, env2);
}
bindings= getTail(bindings);
}
oop ans= nil;
GC_UNPROTECT(tmp);
while (is(Pair, body)) {
ans= eval(getHead(body), env2);
body= getTail(body);
}
GC_UNPROTECT(env2);
return ans;
}
static subr(while)
{
*) _do(div,
/) _do(mod, %)
>)
\
return newBool(getLong(lhs) OP getLong(rhs));
\
fprintf(stderr, "%s: non-numeric argument: ", #OP);
\
if (!is(Long, lhs)) fdumpln(stderr, lhs);
\
else
fdumpln(stderr, rhs);
\
fatal(0);
\
return nil;
\
}
_do_relation()
#undef _do
static subr(eq)
{
arity2(args, "=");
oop lhs= getHead(args);
\
oop rhs= getHead(getTail(args));
\
int ans= 0;
switch (getType(lhs)) {
case Long:
ans= (is(Long, rhs)
));
break;
case String:
ans= (is(String, rhs)
, get(rhs, String,bits)));
break;
default:
ans= (lhs == rhs);
break;
}
return newBool(ans);
}
static subr(ne)
{
arity2(args, "!=");
oop lhs= getHead(args);
\
oop rhs= getHead(getTail(args));
\
int ans= 0;
switch (getType(lhs)) {
case Long:
ans= (is(Long, rhs)
));
break;
case String:
ans= (is(String, rhs)
, get(rhs, String,bits)));
break;
default:
ans= (lhs == rhs);
break;
}
return newBool(!ans);
}
static subr(exit)
{
oop n= car(args);
GC_PROTECT(head);
GC_PROTECT(tail);
GC_UNPROTECT(tail); GC_UNPROTEC
GC_PROTECT(head);
GC_PROTECT(x);
GC_UNPROTECT(x);
static subr(apply_expr)
{
oop fun= car(args);
oop arguments= cdr(args);
oop argl= arguments;
oop defn= get(fun, Expr,defn);
GC_PROTECT(defn);
oop formals= car(defn);
env= get(fun, Expr,env);
GC_PROTECT(env);
oop tmp= nil;
GC_PROTECT(tmp);
while (is(Pair, formals)) {
if (!is(Pair, argl)) {
fprintf(stderr, "\nerror: too few arguments applying ");
fdump(stderr, fun);
fprintf(stderr, " to ");
fdumpln(stderr, arguments);
fatal(0);
}
tmp= newPair(getHead(formals), getHead(argl));
env= newPair(tmp, env);
formals= getTail(formals);
argl= getTail(argl);
}
if (is(Symbol, formals)) {
tmp= newPair(formals, argl);
env= newPair(tmp, env);
argl= nil;
}
if (nil != argl) {
fprintf(stderr, "\nerror: too many arguments applying ");
fdump(stderr, fun);
fprintf(stderr, " to ");
fdumpln(stderr, arguments);
fatal(0);
}
oop ans= nil;
oop body= getTail(defn);
while (is(Pair, body)) {
ans= eval(getHead(body), env);
body= getTail(body);
}
GC_UNPROTECT(tmp);
GC_UNPROTECT(env);
GC_UNPROTECT(defn);
return ans;
}
static subr(apply_fixed)
{
oop fun= car(args);
oop arguments= cadr(args);
return apply(get(fun, Fixed,function), arguments, env);
}
static subr(apply)
{
oop f= car(args);
oop a= car(args);
oop e= car(args);
return apply(f, a,
}
args= cdr(args);
args= cdr(args);
if (nil == e) e= env;
e);
static subr(type_of)
{
arity1(args, "type-of");
return newLong(getType(getHead(args)));
}
static subr(warn)
{
while (is(Pair, args)) {
doprint(stderr, getHead(args), 0);
args= getTail(args);
}
return nil;
}
static subr(print)
{
while (is(Pair, args)) {
print(getHead(args));
args= getTail(args);
}
return nil;
}
static subr(dump)
{
while (is(Pair, args)) {
dump(getHead(args));
args= getTail(args);
}
return nil;
}
static subr(form)
{
arity1(args, "form");
return newForm(getHead(args));
}
static subr(fixedP)
{
arity1(args, "fixed?");
return newBool(is(Fixed, getHead(args)));
}
static subr(cons)
{
arity2(args, "cons");
oop lhs= getHead(args);
oop rhs= getHead(getTail(args));
return newPair(lhs, rhs);
}
static subr(pairP)
{
arity1(args, "pair?");
return newBool(is(Pair, getHead(args)));
}
static subr(car)
{
arity1(args, "car");
return car(getHead(args));
}
static subr(set_car)
{
arity2(args, "set-car");
oop arg= getHead(args);
rn nil;
return setHead(arg, getHead(getTail(args)));
}
static subr(cdr)
{
arity1(args, "cdr");
return cdr(getHead(args));
}
static subr(set_cdr)
{
arity2(args, "set-cdr");
oop arg= getHead(args);
rn nil;
return setTail(arg, getHead(getTail(args)));
}
static subr(formP)
{
arity1(args, "form?");
return newBool(is(Form, getHead(args)));
}
static subr(symbolP)
{
arity1(args, "symbol?");
return newBool(is(Symbol, getHead(args)));
}
static subr(stringP)
{
arity1(args, "string?");
return newBool(is(String, getHead(args)));
}
static subr(string)
{
oop arg= car(args);
int num= is(Long, arg) ? getLong(arg) : 0;
return _newString(num);
}
static subr(string_length)
{
arity1(args, "string-length");
oop arg= getHead(args);
if (!is(String, arg)) { fprintf(stderr,
"string-length: non-String argument: "); fdumpln(stderr, arg); fatal(0); }
return newLong(stringLength(arg));
}
static subr(string_at)
{
arity2(args, "string-at");
oop arr= getHead(args);
if (!is(String, arr)) { fprintf(stderr,
"string-at: non-String argument: "); fdumpln(stderr, arr); fatal(0); }
oop arg= getHead(getTail(args));
if (!is(Long, arg)) return nil;
int idx= getLong(arg);
if (0 <= idx && idx < stringLength(arr)) return newLong(get(arr, String,bits)[
idx]);
return nil;
}
static subr(set_string_at)
{
arity3(args, "set-string-at");
oop arr= getHead(args);
if (!is(String, arr)) { fprintf(
stderr, "set-string-at: non-string argument: "); fdumpln(stderr, arr); fatal(0
); }
oop arg= getHead(getTail(args));
if (!is(Long, arg)) { fprintf(st
derr, "set-string-at: non-integer index: "); fdumpln(stderr, arg); fatal(0); }
oop val= getHead(getTail(getTail(args)));
if (!is(Long, val)) { fprintf(st
derr, "set-string-at: non-integer value: "); fdumpln(stderr, val); fatal(0); }
int idx= getLong(arg);
if (0 <= idx && idx < stringLength(arr)) {
get(arr, String,bits)[idx]= getLong(val);
return val;
}
return nil;
}
static subr(string_symbol)
{
oop arg= car(args);
if (!is(String, arg)) return nil;
return intern(get(arg, String,bits));
}
static subr(symbol_string)
{
oop arg= car(args);
static subr(array)
{
oop arg= car(args);
int num= is(Long, arg) ? getLong(arg) : 0;
return newArray(num);
}
static subr(arrayP)
{
return is(Array, car(args)) ? s_t : nil;
}
static subr(array_length)
{
arity1(args, "array-length");
oop arg= getHead(args);
if (!is(Array, arg)) { fprintf(stderr, "
array-length: non-Array argument: "); fdumpln(stderr, arg); fatal(0); }
return newLong(arrayLength(arg));
}
static subr(array_at)
{
arity2(args, "array-at");
oop arr= getHead(args);
oop arg= getHead(getTail(args));
return arrayAt(arr, getLong(arg));
}
static subr(set_array_at)
{
arity3(args, "set-array-at");
oop arr= getHead(args);
oop arg= getHead(getTail(args));
oop val= getHead(getTail(getTail(args)));
return arrayAtPut(arr, getLong(arg), val);
}
static subr(allocate)
{
arity2(args, "allocate");
oop type= getHead(args);
if (!is(Long, type)) return nil;
oop size= getHead(getTail(args));
if (!is(Long, size)) return nil;
return _newOops(getLong(type), sizeof(oop) * getLong(size));
}
static subr(oop_at)
{
arity2(args, "oop-at");
oop obj= getHead(args);
oop arg= getHead(getTail(args));
return oopAt(obj, getLong(arg));
}
static subr(set_oop_at)
{
arity3(args, "set-oop-at");
oop obj= getHead(args);
oop arg= getHead(getTail(args));
oop val= getHead(getTail(getTail(args)));
return oopAtPut(obj, getLong(arg), val);
}
static subr(not)
{
arity1(args, "not");
oop obj= getHead(args);
return (nil == obj) ? s_t : nil;
}
#undef subr
static void replFile(FILE *stream)
{
for (;;) {
if (stream == stdin) {
printf(".");
fflush(stdout);
}
oop obj= read(stream);
if (obj == (oop)EOF) break;
GC_PROTECT(obj);
if (opt_v) {
dumpln(obj);
fflush(stdout);
}
obj= expand(obj, globals);
obj= encode(obj, globals);
obj= eval(obj, globals);
if (stream == stdin) {
printf(" => ");
fflush(stdout);
dumpln(obj);
fflush(stdout);
}
GC_UNPROTECT(obj);
if (opt_v) {
GC_gcollect();
printf("%ld collections, %ld objects, %ld bytes, %4.1f%% fragmentation\n",
(long)GC_collections, (long)GC_count_objects(), (long)GC_count_byte
s(),
GC_count_fragments() * 100.0);
}
}
int c= getc(stream);
if (EOF != c)
fatal("unexpected character 0x%02x '%c'\
n", c, c);
}
=
=
=
=
=
=
=
=
=
intern("set");
intern("let");
intern("lambda");
intern("quote");
intern("quasiquote");
intern("unquote");
intern("unquote-splicing");
intern("t");
intern(".");
GC_PROTECT(tmp);
define(intern("*expanders*"),
tmp, globals)
define(intern("*encoders*"),
tmp, globals)
;
;
tmp= newArray(32); evaluators= define(intern("*evaluators*"), tmp, globals)
;
tmp= newArray(32); applicators= define(intern("*applicators*"), tmp, globals)
;
arrayAtPut(getTail(evaluators), Symbol, newSubr(subr_eval_symbol, "eval-symbo
l"));
arrayAtPut(getTail(evaluators), Pair, newSubr(subr_eval_pair, "eval-pair"
));
arrayAtPut(getTail(applicators), Fixed, newSubr(subr_apply_fixed, "apply-fixe
d"));
arrayAtPut(getTail(applicators), Expr,
" ));
traceStack= newArray(32);
backtrace=
newSubr(subr_apply_expr, "apply-expr
GC_add_root(&traceStack);
{
{
{
{
{
{
{
{
{
{
{
{
{
{
{
{
{
{
{
" not",
" ~",
" +",
" -",
" *",
" /",
" %",
" &",
" |",
" ^",
" <<",
" >>",
" <",
" <=",
" =",
" !=",
" >=",
" >",
0,
subr_not },
subr_com },
subr_add },
subr_sub },
subr_mul },
subr_div },
subr_mod },
subr_bitand },
subr_bitor },
subr_bitxor },
subr_shl },
subr_shr },
subr_lt },
subr_le },
subr_eq },
subr_ne },
subr_ge },
subr_gt },
0 }
};
for (ptr= subrs; ptr->name; ++ptr) {
tmp= newSubr(ptr->imp, ptr->name + 1);
if ('.' == ptr->name[0]) tmp= newFixed(tmp);
define(intern(ptr->name + 1), tmp, globals);
}
}
tmp= nil;
f_set=
f_quote=
f_lambda=
f_let=
GC_UNPROTECT(tmp);
cdr(assq(s_set,
cdr(assq(s_quote,
cdr(assq(s_lambda,
cdr(assq(s_let,
globals));
globals));
globals));
globals));
GC_add_root(&f_set);
GC_add_root(&f_quote);
GC_add_root(&f_lambda);
GC_add_root(&f_let);
int repled= 0;
signal(SIGINT, sigint);
while (argc-- > 1) {
++argv;
if
(!strcmp(*argv, "-v"))
else {
replPath(*argv);
repled= 1;
}
}
++opt_v;
if (opt_v) {
GC_gcollect();
printf("%ld collections, %ld objects, %ld bytes, %4.1f%% fragmentation\n",
(long)GC_collections, (long)GC_count_objects(), (long)GC_count_bytes(
),
GC_count_fragments() * 100.0);
}
if (!repled) {
replFile(stdin);
printf("\nmorituri te salutant\n");
}
return 0;
}