Changed from a linear probing hash table to a hash chain method since we now have better storage allocation. This is more space efficient and removes the static limits on local variable table sizes.

git-svn-id: http://picoc.googlecode.com/svn/trunk@41 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
zik.saleeba 2009-01-29 22:26:04 +00:00
parent b2396d3eda
commit 2d7b467b96
4 changed files with 30 additions and 55 deletions

View file

@ -22,7 +22,9 @@ void ProgramFail(struct LexState *Lexer, const char *Message, ...)
{
va_list Args;
StrPrintf("%S:%d: ", Lexer->FileName, Lexer->Line);
if (Lexer != NULL)
StrPrintf("%S:%d: ", Lexer->FileName, Lexer->Line);
va_start(Args, Message);
vStrPrintf(Message, Args);
StrPrintf("\n");

View file

@ -156,12 +156,14 @@ struct TableEntry
{
Str Key;
struct Value *Val;
struct TableEntry *Next;
};
struct Table
{
short Size;
struct TableEntry *HashTable;
short OnHeap;
struct TableEntry **HashTable;
};
/* stack frame for function calls */
@ -169,7 +171,7 @@ struct StackFrame
{
struct LexState ReturnLex; /* how we got here */
struct Table LocalTable; /* the local variables and parameters */
struct TableEntry LocalHashTable[LOCAL_TABLE_SIZE];
struct TableEntry *LocalHashTable[LOCAL_TABLE_SIZE];
struct StackFrame *PreviousStackFrame; /* the next lower stack frame */
};
@ -202,7 +204,7 @@ void ProgramFail(struct LexState *Lexer, const char *Message, ...);
void ScanFile(const Str *FileName);
/* table.c */
void TableInit(struct Table *Tbl, struct TableEntry *HashTable, int Size);
void TableInit(struct Table *Tbl, struct TableEntry **HashTable, int Size, int OnHeap);
int TableSet(struct Table *Tbl, const Str *Key, struct Value *Val);
int TableGet(struct Table *Tbl, const Str *Key, struct Value **Val);

67
table.c
View file

@ -1,7 +1,7 @@
#include <string.h>
#include "picoc.h"
/* hash function */
/* quick hash function */
static unsigned int TableHash(const Str *Key)
{
if (Key->Len == 0)
@ -11,53 +11,27 @@ static unsigned int TableHash(const Str *Key)
}
/* initialise a table */
void TableInit(struct Table *Tbl, struct TableEntry *HashTable, int Size)
void TableInit(struct Table *Tbl, struct TableEntry **HashTable, int Size, int OnHeap)
{
Tbl->Size = Size;
Tbl->OnHeap = OnHeap;
Tbl->HashTable = HashTable;
memset(HashTable, '\0', sizeof(struct TableEntry) * Size);
memset(HashTable, '\0', sizeof(struct TableEntry *) * Size);
}
static int TableCheckEntry(struct Table *Tbl, const Str *Key, int HashPos)
{
struct TableEntry *Entry = &Tbl->HashTable[HashPos];
if (Entry->Key.Len == 0)
return -1; /* empty */
else if (StrEqual(&Entry->Key, Key))
return HashPos; /* found */
else
return -2; /* wrong key */
}
/* search a table for an identifier. sets AddAt to where to add it at if not found */
/* check a hash table entry for a key */
static int TableSearch(struct Table *Tbl, const Str *Key, int *AddAt)
{
int HashValue;
int HashPos;
int Result;
struct TableEntry *Entry;
int HashValue = TableHash(Key) % Tbl->Size;;
HashValue = TableHash(Key) % Tbl->Size;
for (HashPos = HashValue; HashPos < Tbl->Size; HashPos++)
for (Entry = Tbl->HashTable[HashValue]; Entry != NULL; Entry = Entry->Next)
{
*AddAt = HashPos;
if ( (Result = TableCheckEntry(Tbl, Key, HashPos)) != -2)
return Result;
if (StrEqual(&Entry->Key, Key))
return HashValue; /* found */
}
for (HashPos = 0; HashPos < HashValue; HashPos++)
{
*AddAt = HashPos;
if ( (Result = TableCheckEntry(Tbl, Key, HashPos)) != -2)
return Result;
}
/* not found and table is full */
*AddAt = -1;
*AddAt = HashValue; /* didn't find it in the chain */
return -1;
}
@ -70,16 +44,13 @@ int TableSet(struct Table *Tbl, const Str *Key, struct Value *Val)
HashPos = TableSearch(Tbl, Key, &AddAt);
if (HashPos == -1)
{
if (AddAt == -1)
Fail("variable table is full\n");
else
{ /* add it to the table */
struct TableEntry *Entry = &Tbl->HashTable[AddAt];
Entry->Key = *Key;
Entry->Val = Val;
return TRUE;
}
{ /* add it to the table */
struct TableEntry *NewEntry = VariableAlloc(NULL, sizeof(struct TableEntry), Tbl->OnHeap);
NewEntry->Key = *Key;
NewEntry->Val = Val;
NewEntry->Next = Tbl->HashTable[AddAt];
Tbl->HashTable[AddAt] = NewEntry;
return TRUE;
}
return FALSE;
@ -96,6 +67,6 @@ int TableGet(struct Table *Tbl, const Str *Key, struct Value **Val)
if (HashPos == -1)
return FALSE;
*Val = Tbl->HashTable[HashPos].Val;
*Val = Tbl->HashTable[HashPos]->Val;
return TRUE;
}

View file

@ -4,7 +4,7 @@
/* the table of global definitions */
struct Table GlobalTable;
struct TableEntry GlobalHashTable[GLOBAL_TABLE_SIZE];
struct TableEntry *GlobalHashTable[GLOBAL_TABLE_SIZE];
/* the stack */
struct StackFrame *TopStackFrame = NULL;
@ -13,7 +13,7 @@ struct StackFrame *TopStackFrame = NULL;
/* initialise the variable system */
void VariableInit()
{
TableInit(&GlobalTable, &GlobalHashTable[0], GLOBAL_TABLE_SIZE);
TableInit(&GlobalTable, &GlobalHashTable[0], GLOBAL_TABLE_SIZE, TRUE);
TopStackFrame = NULL;
}
@ -119,7 +119,7 @@ void VariableStackFrameAdd(struct LexState *Lexer)
HeapPushStackFrame();
NewFrame = HeapAllocStack(sizeof(struct StackFrame));
NewFrame->ReturnLex = *Lexer;
TableInit(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0], LOCAL_TABLE_SIZE);
TableInit(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0], LOCAL_TABLE_SIZE, FALSE);
NewFrame->PreviousStackFrame = TopStackFrame;
TopStackFrame = NewFrame;
}