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:
parent
b2396d3eda
commit
2d7b467b96
4
picoc.c
4
picoc.c
|
@ -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");
|
||||
|
|
8
picoc.h
8
picoc.h
|
@ -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
67
table.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue