Real hashmap

This commit is contained in:
attilavs2 2025-03-05 14:38:36 +01:00
parent 238bc31425
commit e0d78813d0
14 changed files with 70 additions and 52 deletions

0
.gitignore vendored Normal file → Executable file
View file

1
Makefile Normal file → Executable file
View file

@ -27,6 +27,7 @@ windef:
$(eval OUTPUT = "$(OUTNAME).exe")
$(eval BUILD_DIR = build-win)
$(eval LDFLAGS = $(LDFLAGS_WIN))
$(eval CFLAGS += -mno-ms-bitfields -D win)
builddir:
@- mkdir $(BUILD_DIR)

0
examples/hello_world.flsp Normal file → Executable file
View file

0
examples/more_or_less.flsp Normal file → Executable file
View file

0
spec.md Normal file → Executable file
View file

19
src/byte_defs.h Normal file → Executable file
View file

@ -73,41 +73,44 @@ typedef struct {
typedef struct {
u8 __padding[2];
u32 value;
u8 __padding[2];
} PACKED Value4B;
typedef struct {
u16 len;
u32 pos; // Offset from stack allocator
u16 len;
} PACKED ValueArray;
typedef struct {
u8 len;
union {
PACKED union {
char str[5];
struct {
u8 __padding;
PACKED struct {
u32 pos;
u8 __padding;
};
};
u8 len;
} PACKED ValueStr;
typedef struct {
uint is_array : 1;
uint type : 15;
PACKED union {
Value4B v4B;
ValueArray varray;
};
uint is_array : 1;
uint type : 15;
} PACKED Value;
#ifndef win
_Static_assert(sizeof(Value) == 8);
#endif

9
src/bytecode.c Executable file
View file

@ -0,0 +1,9 @@
#include <string.h>
#include <stdlib.h>
#include "types.h"
#include "byte_defs.h"
void run_bytecode(){
}

0
src/code_defs.h Normal file → Executable file
View file

0
src/config.h Normal file → Executable file
View file

0
src/fixed.h Normal file → Executable file
View file

49
src/hash.c Normal file → Executable file
View file

@ -10,6 +10,7 @@ int heap_hashmap(HashMap *map, i32 size){
if(size < 32)
return 1;
map->curr_len = size;
map->curr_id = 0;
map->buffer = malloc(sizeof(MapItem)*size);
map->bit_free = malloc(sizeof(u32)*size/32);
@ -27,7 +28,7 @@ void free_hashmap(HashMap *map){
}
// ~djb2
u32 hash(i32 max, char *str){
i32 hash(i32 max, char *str){
if(!str)
return HASH_NULL;
u32 hsh = 5281;
@ -51,44 +52,42 @@ void set_bit(u32 *bitmap, i32 pos){
bitmap[pos/32] |= (1<<(pos%32));
}
u32 hashmap_insert(HashMap *map, char *str){
i32 hashmap_insert(HashMap *map, char *str){
#if DEBUG > 0
float load_factor = (float)(map->item_n+1)/(float)(map->curr_len);
//printf("%f\n", load_factor);
#if DEBUG == 1
assert(load_factor < 0.95);
#else
assert(load_factor < 0.8);
#else
assert(load_factor < 0.7);
#endif
#endif
if(map->item_n+1 >= map->curr_len)
return HASH_NULL;
u32 hsh = hash(map->curr_len, str);
char *match = hashmap_get(map, hsh);
if(match){
if(!strncmp(match, str, 32))
return hsh;
i32 hsh = hash(map->curr_len, str);
i32 match = hashmap_get(map, str);
if(match > 0){
return match;
}
if(!map->bit_free[hsh/32]){
printf("[ncan]");
map->buffer[hsh].hash = hsh;
map->buffer[hsh].id = map->curr_id++;
strncpy(map->buffer[hsh].str, str, 32);
set_bit(map->bit_free, hsh);
map->item_n++;
return hsh;
return map->buffer[hsh].id;
}
u32 pos = hsh;
i32 pos = hsh;
i32 taken;
do {
taken = get_bit(map->bit_free, pos);
if(!taken)
break;
pos++;
} while(pos < map->curr_len);
printf("(%d %d)", hsh, pos);
} while(pos < map->curr_len && pos-hsh < RELOCATE_TRY_MAX);
#if DEBUG == 2
assert(!taken);
@ -96,28 +95,32 @@ u32 hashmap_insert(HashMap *map, char *str){
if(!taken){
map->buffer[pos].hash = hsh;
strncpy(map->buffer[hsh].str, str, 32);
map->buffer[pos].id = map->curr_id++;
strncpy(map->buffer[pos].str, str, 32);
set_bit(map->bit_free, hsh);
map->item_n++;
return hsh;
return map->buffer[pos].id;
}
return HASH_NULL;
}
char *hashmap_get(HashMap *map, u32 fhash){
u32 pos = fhash;
i32 hashmap_get(HashMap *map, char *str){
i32 fhash = hash(map->curr_len, str);
i32 pos = fhash;
i32 match;
do {
u32 c_hash = map->buffer[pos].hash;
i32 c_hash = map->buffer[pos].hash;
match = c_hash == fhash;
printf("[%d %d]", c_hash, fhash);
if(match)
match = !strncmp(str,map->buffer[pos].str,32);
pos++;
} while(!match && pos < map->curr_len);
} while(!match && pos < map->curr_len && pos-fhash < RELOCATE_TRY_MAX);
pos--;
if(match)
return map->buffer[pos].str;
return map->buffer[pos].id;
else
return NULL;
return -1;
}

16
src/hash.h Normal file → Executable file
View file

@ -7,12 +7,13 @@
#define HASH_NULL 0xFFFFFF
#define LOAD_EXTEND fix(0.7)
#define RELOCATE_TRY_MAX 32
typedef struct {
u32 hash; // Hashs are internally 24bit for bytecode ops
i32 hash; // Hashs are internally 24bit for bytecode ops
char str[32];
i32 id;
} MapItem;
@ -20,8 +21,9 @@ typedef struct {
MapItem *buffer;
u32 *bit_free; // Bit map to track usage
u32 curr_len;
u32 item_n;
i32 curr_len;
i32 item_n;
i32 curr_id;
} HashMap;
@ -30,9 +32,9 @@ int heap_hashmap(HashMap *map, i32 size);
void free_hashmap(HashMap *map);
// Max is max value of hash
u32 hash(i32 max, char *str);
i32 hash(i32 max, char *str);
// Returns hash - if error returns HASH_NULL
u32 hashmap_insert(HashMap *map, char *str);
i32 hashmap_insert(HashMap *map, char *str);
char *hashmap_get(HashMap *map, u32 hash);
i32 hashmap_get(HashMap *map, char *str);

18
src/main.c Normal file → Executable file
View file

@ -11,9 +11,10 @@
#define STR_N 20
int main(){
HashMap map;
if(heap_hashmap(&map, 256)){
printf("Failed to alloc hashmap");
if(heap_hashmap(&map, 256) ){
printf("Failed to alloc hashmap\n");
return 1;
}
@ -40,19 +41,14 @@ int main(){
"b"
};
char *strings2[STR_N];
int hashs[STR_N];
int ids[STR_N];
for(int i = 0; i < STR_N; i++)
hashs[i] = hashmap_insert(&map, strings[i]);
for(int i = 0; i < STR_N; i++){
strings2[i] = hashmap_get(&map, hashs[i]);
printf("%d : %s\n", hashs[i], strings2[i]);
}
ids[i] = hashmap_insert(&map, strings[i]);
i32 res = 0;
for(int i = 0; i < STR_N; i++){
res += strncmp(strings[i], strings2[i], 32);
res = ids[i] - hashmap_get(&map, strings[i]);
printf("%s : %d:%d\n", strings[i], hashmap_get(&map, strings[i]),ids[i]);
}
assert(!res);

4
src/types.h Normal file → Executable file
View file

@ -13,5 +13,9 @@ typedef uint64_t u64;
typedef unsigned int uint;
#ifdef win
#define PACKED __attribute__((gcc_struct)) __attribute__((__packed__))
#else
#define PACKED __attribute__((__packed__))
#endif