intern symbols using hash table

This commit is contained in:
Yuichi Nishiwaki 2013-10-20 14:05:35 +09:00
parent bde09e063a
commit 7322271d65
5 changed files with 90 additions and 10 deletions

View File

@ -13,6 +13,7 @@
#define PIC_STACK_SIZE 1024
#define PIC_IREP_SIZE 256
#define PIC_GLOBALS_SIZE 1024
#define PIC_SYM_TBL_SIZE 128
/* enable all debug flags */
#define DEBUG 1

View File

@ -27,6 +27,8 @@ typedef struct {
pic_value sADD, sSUB, sMUL, sDIV;
struct pic_env *global_env;
struct sym_tbl *sym_tbl;
pic_value *globals;
size_t glen, gcapa;
struct pic_irep **irep;

12
include/picrin/symbol.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef SYMBOL_H__
#define SYMBOL_H__
struct sym_tbl {
pic_value tbl[PIC_SYM_TBL_SIZE];
size_t size;
};
struct sym_tbl * sym_tbl_new();
pic_value sym_tbl_get(struct sym_tbl *, const char *);
#endif

View File

@ -3,9 +3,10 @@
#include "picrin.h"
#include "picrin/gc.h"
#include "picrin/proc.h"
#include "picrin/symbol.h"
static struct pic_env *
pic_new_empty_env()
new_empty_env()
{
struct pic_env *env;
@ -37,6 +38,9 @@ pic_open()
pic->heap = (struct heap_page *)malloc(sizeof(struct heap_page));
init_heap_page(pic->heap);
/* symbol table */
pic->sym_tbl = sym_tbl_new();
/* irep */
pic->irep = (struct pic_irep **)malloc(sizeof(struct pic_irep *) * PIC_IREP_SIZE);
pic->ilen = 0;
@ -64,7 +68,7 @@ pic_open()
pic->sDIV = pic_intern_cstr(pic, "/");
/* global environment */
pic->global_env = pic_new_empty_env();
pic->global_env = new_empty_env();
pic_init_core(pic);
return pic;

View File

@ -2,19 +2,80 @@
#include <stdlib.h>
#include "picrin.h"
#include "picrin/pair.h"
#include "picrin/symbol.h"
static int
str_hash(const char *str)
{
int hash = 0, len, i;
len = strlen(str);
for (i = 0; i < len; ++i) {
hash = hash * 31 + str[i];
}
return hash;
}
struct sym_tbl *
sym_tbl_new()
{
struct sym_tbl *s_tbl;
int i;
s_tbl = (struct sym_tbl *)malloc(sizeof(struct sym_tbl));
s_tbl->size = PIC_SYM_TBL_SIZE;
for (i = 0; i < PIC_SYM_TBL_SIZE; ++i) {
s_tbl->tbl[i] = pic_nil_value();
}
return s_tbl;
}
pic_value
pic_intern_cstr(pic_state *pic, const char *name)
sym_tbl_get(struct sym_tbl *s_tbl, const char *key)
{
struct pic_symbol *sym;
size_t len;
int hash, idx;
pic_value v, k;
char *name;
sym = (struct pic_symbol*)pic_obj_alloc(pic, sizeof(struct pic_symbol), PIC_TT_SYMBOL);
hash = str_hash(key);
idx = hash % s_tbl->size;
for (v = s_tbl->tbl[idx]; ! pic_nil_p(v); v = pic_pair_ptr(v)->cdr) {
k = pic_pair_ptr(v)->car;
name = pic_symbol_ptr(k)->name;
if (strcmp(name, key) == 0) {
return k;
}
}
return pic_undef_value();
}
pic_value
pic_intern_cstr(pic_state *pic, const char *str)
{
pic_value v;
int len, hash, idx;
char *new_str;
struct pic_symbol *sym;
v = sym_tbl_get(pic->sym_tbl, str);
if (! pic_undef_p(v)) {
return v;
}
/* clone name string */
len = strlen(name);
sym->name = (char *)pic_alloc(pic, len + 1);
strncpy(sym->name, name, len + 1);
len = strlen(str);
new_str = (char *)pic_alloc(pic, len + 1);
strncpy(new_str, str, len + 1);
return pic_obj_value(sym);
sym = (struct pic_symbol*)pic_obj_alloc(pic, sizeof(struct pic_symbol), PIC_TT_SYMBOL);
sym->name = new_str;
v = pic_obj_value(sym);
hash = str_hash(str);
idx = hash % pic->sym_tbl->size;
pic->sym_tbl->tbl[idx] = pic_cons(pic, v, pic->sym_tbl->tbl[idx]);
return v;
}