Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
160 lines (126 sloc) 2.85 KB
inline C <<end
#include <string.h>
#include "symbol.h"
#include <stdlib.h>
#include <string.h>
#include "symbol.h"
#include "gen.h"
#include "prim.h"
#include "array.h"
typedef struct symbol *symbol;
struct symbol {
datum next;
datum name;
};
static size_t fill = 0;
datum symbols = nil;
/* Yikes, this is expensive. There has got to be a better way. */
static uint
next_prime(uint n)
{
uint i;
if (n < 2) return 2;
if (n % 2 == 0) ++n;
for (;; n += 2) {
for (i = 3; i * i <= n && n % i != 0; i += 2) {}
if (i * i > n) return n;
}
}
static datum store(symbol ent);
static void
rehash()
{
datum *old, *new;
size_t old_cap = datum_size(symbols), i;
new = (datum *) make_array(next_prime(datum_size(symbols) << 1));
/* do this after allocating new array; the old one might have moved */
old = (datum *) symbols;
symbols = (datum) new;
fill = 0;
for (i = 0; i < old_cap; i++) {
while (old[i] != nil) {
symbol ent = (symbol) old[i];
old[i] = ent->next;
ent->next = nil;
store(ent);
}
}
}
static uint
hash(size_t n, const char *name)
{
return 0;
}
static datum
store(symbol ent)
{
int i;
if (fill >= (datum_size(symbols) << 2)) rehash();
i = hash(datum_size(ent->name), (char *) ent->name) % datum_size(symbols);
fill++;
ent->next = (datum) symbols[i];
return ((datum *) symbols)[i] = (datum) ent;
}
static datum
make_symbol(size_t len, const char *name)
{
return make_record_permanent(2, symbol_mtab, nil,
make_str_init_permanent(len, name));
}
static datum
lookup_sym(size_t len, const char *name)
{
int i;
datum sh;
if (!datum_size(symbols)) return nil;
i = hash(len, name) % datum_size(symbols);
for (sh = (datum) symbols[i]; sh != nil; sh = ((symbol) sh)->next) {
if (str_cmp_charstar(((symbol) sh)->name, len, name) == 0) {
return sh;
}
}
return nil;
}
static datum
intern_len(size_t len, const char *name)
{
datum sym;
sym = lookup_sym(len, name);
if (sym != nil) return sym;
return store((symbol) make_symbol(len, name));
}
datum
intern(const char *name)
{
return intern_len(strlen(name), name);
}
datum
intern_str(datum name)
{
return intern_len(datum_size(name), (char *) name);
}
void
pr_symbol(int fd, datum sym)
{
if (!symbolp(sym)) return prfmt(fd, "<bad-symbol>");
prfmt(fd, "%o", ((symbol) sym)->name);
}
int
symbolp(datum x)
{
return (!(((size_t)x)&1) &&
(datum_size(x) == 2) &&
((datum) x[-1]) == symbol_mtab);
}
size_t
symbol_copy0(char *dest, size_t n, datum sym)
{
if (!symbolp(sym)) die1("not a symbol", sym);
return copy_str_contents0(dest, ((symbol) sym)->name, n);
}
end
def symbol: sobj:
inline C str <<end
return ((symbol) rcv)->name;
end
. '()