🔥 use list to implement hashmap

This commit is contained in:
ValKmjolnir 2024-11-21 20:32:49 +08:00
parent 4e29025f7a
commit 563617b6d3
4 changed files with 99 additions and 118 deletions

View File

@ -18,8 +18,8 @@ ast::type_def* type_replace_pass::generate_generic_type(const type& t,
const span& loc) {
auto new_def = new type_def(loc);
new_def->set_name(new identifier(loc, t.name));
new_def->get_name()->set_redirect_location(ctx.this_file);
new_def->set_redirect_location(ctx.this_file);
new_def->get_name()->set_redirect_location(t.loc_file);
new_def->set_redirect_location(t.loc_file);
if (t.is_immutable) {
new_def->set_constant();
}
@ -40,26 +40,27 @@ ast::type_def* type_replace_pass::generate_generic_type(const type& t,
bool type_replace_pass::visit_type_def(type_def* node) {
const auto name = node->get_name()->get_name();
if (g_data.types.count(name)) {
node->get_name()->reset_name(g_data.types.at(name).name);
node->get_name()->set_redirect_location(ctx.this_file);
node->set_redirect_location(ctx.this_file);
const auto& select_type = g_data.types.at(name);
node->get_name()->reset_name(select_type.name);
node->get_name()->set_redirect_location(select_type.loc_file);
node->set_redirect_location(select_type.loc_file);
for (i64 i = 0; i < g_data.types.at(name).pointer_depth; ++i) {
for (i64 i = 0; i < select_type.pointer_depth; ++i) {
node->add_pointer_level();
}
if (!g_data.types.at(name).generics.empty() &&
if (!select_type.generics.empty() &&
node->get_generic_types()) {
err.err(node->get_name()->get_location(),
"replace type \"" + g_data.types.at(name).full_path_name() +
"replace type \"" + select_type.full_path_name() +
"\" is already a generic type, not allowed to replace \"" +
name + "\"."
);
}
if (!g_data.types.at(name).generics.empty() &&
if (!select_type.generics.empty() &&
!node->get_generic_types()) {
node->set_generic_types(new generic_type_list(node->get_location()));
for(const auto& i : g_data.types.at(name).generics) {
for(const auto& i : select_type.generics) {
node->get_generic_types()->add_type(
generate_generic_type(i, node->get_location())
);
@ -75,29 +76,30 @@ bool type_replace_pass::visit_type_def(type_def* node) {
bool type_replace_pass::visit_call_id(ast::call_id* node) {
const auto name = node->get_id()->get_name();
if (g_data.types.count(name)) {
node->get_id()->set_name(g_data.types.at(name).name);
node->get_id()->set_redirect_location(ctx.this_file);
node->set_redirect_location(ctx.this_file);
const auto& select_type = g_data.types.at(name);
node->get_id()->set_name(select_type.name);
node->get_id()->set_redirect_location(select_type.loc_file);
node->set_redirect_location(select_type.loc_file);
if (g_data.types.at(name).pointer_depth) {
if (select_type.pointer_depth) {
err.err(node->get_id()->get_location(),
"replace type \"" + g_data.types.at(name).full_path_name() +
"replace type \"" + select_type.full_path_name() +
"\" is a pointer type, which is not allowed here."
);
}
if (!g_data.types.at(name).generics.empty() &&
if (!select_type.generics.empty() &&
node->get_generic_types()) {
err.err(node->get_id()->get_location(),
"replace type \"" + g_data.types.at(name).full_path_name() +
"replace type \"" + select_type.full_path_name() +
"\" is already a generic type, not allowed to replace \"" +
name + "\"."
);
}
if (!g_data.types.at(name).generics.empty() &&
if (!select_type.generics.empty() &&
!node->get_generic_types()) {
node->set_generic_types(new generic_type_list(node->get_location()));
for(const auto& i : g_data.types.at(name).generics) {
for(const auto& i : select_type.generics) {
node->get_generic_types()->add_type(
generate_generic_type(i, node->get_location())
);

View File

@ -13,6 +13,12 @@ func compile(option: cli_option) {
err.out(">, check if exists and is readable\n");
return;
}
if (fs::is_dir(option.input_file)) {
err.red().out("Error: ").reset();
err.out("failed to load file <").out(option.input_file);
err.out(">, this is a directory\n");
return;
}
if (option.library_path != nil && !fs::is_dir(option.library_path)) {
err.red().out("Error: ").reset();
err.out("failed to load library path <").out(option.library_path);

View File

@ -1,6 +1,6 @@
use std::str::{ str };
use std::libc::{ malloc, free, streq };
use std::list::{ list };
use std::list::{ list, list_iter };
pub struct pair<K, V> {
key: K*,
@ -14,124 +14,98 @@ impl pair<K, V> {
free(self->key => i8*);
free(self->value => i8*);
}
}
pub struct bucket<K, V> {
pair: pair<K, V>,
next: bucket<K, V>*
}
impl bucket<K, V> {
pub func delete(self) {
self->pair.delete();
pub func copy(self) -> pair<K, V>* {
var res = pair<K, V>::__alloc__();
res->key = self->key->copy();
res->value = self->value->copy();
return res;
}
}
pub struct hashmap<K, V> {
size: u64,
data_capacity: u64,
data: bucket<K, V>**
data: list<pair<K, V>>*
}
impl hashmap<K, V> {
pub func new() -> hashmap<K, V>* {
var res = hashmap<K, V>::__alloc__();
res->size = 0 => u64;
res->data_capacity = 1024 => u64;
res->data = malloc(res->data_capacity * (8 => u64)) => bucket<K, V>**;
for (var i = 0 => u64; i < res->data_capacity; i += 1 => u64) {
res->data[i] = nil => bucket<K, V>*;
}
res->init();
return res;
}
pub func instance() -> hashmap<K, V> {
var res = hashmap<K, V> {
size: 0 => u64,
data_capacity: 1024 => u64,
data: malloc((1024 * 8) => u64) => bucket<K, V>**
};
for (var i = 0 => u64; i < res.data_capacity; i += 1 => u64) {
res.data[i] = nil => bucket<K, V>*;
}
var res = hashmap<K, V> {};
res.init();
return res;
}
func init(self) {
self->size = 0 => u64;
self->data_capacity = 1024 => u64;
self->data = malloc(self->data_capacity
* list<pair<K, V>>::__size__())
=> list<pair<K, V>>*;
for (var i = 0 => u64; i < self->data_capacity; i += 1 => u64) {
self->data[i] = list<pair<K, V>>::instance();
}
}
pub func delete(self) {
for (var i = 0 => u64; i < self->data_capacity; i += 1 => u64) {
var bucket_list = self->data[i];
while (bucket_list => i8* != nil) {
var next = bucket_list->next;
bucket_list->delete();
free(bucket_list => i8*);
bucket_list = next;
}
self->data[i].delete();
}
free(self->data => i8*);
self->size = 0 => u64;
self->data_capacity = 0 => u64;
self->data = nil => bucket<K, V>**;
self->data = nil => list<pair<K, V>>*;
}
}
impl hashmap<K, V> {
pub func has(self, key: K*) -> bool {
var hash = key->hash() % (1024 => u64);
var bucket_list = self->data[hash];
while (bucket_list => i8* != nil) {
if (bucket_list->pair.key->eq(key)) {
var bucket = self->data[hash].__ptr__();
for (var i = bucket->iter(); !i.is_end(); i = i.next()) {
if (i.elem()->key->eq(key)) {
return true;
}
bucket_list = bucket_list->next;
}
return false;
}
pub func get(self, key: K*) -> V* {
var hash = key->hash() % (1024 => u64);
var bucket_list = self->data[hash];
while (bucket_list => i8* != nil) {
if (bucket_list->pair.key->eq(key)) {
return bucket_list->pair.value;
var bucket = self->data[hash].__ptr__();
for (var i = bucket->iter(); !i.is_end(); i = i.next()) {
if (i.elem()->key->eq(key)) {
return i.elem()->value;
}
bucket_list = bucket_list->next;
}
}
return nil => V*;
}
pub func insert(self, key: K*, value: V*) {
var hash = key->hash() % self->data_capacity;
var bucket_list = self->data[hash];
while (bucket_list => i8* != nil) {
// do replacement
if (bucket_list->pair.key->eq(key)) {
bucket_list->pair.value->delete();
free(bucket_list->pair.value => i8*);
bucket_list->pair.value = value->copy();
var bucket = self->data[hash].__ptr__();
for (var i = bucket->iter(); !i.is_end(); i = i.next()) {
if (i.elem()->key->eq(key)) {
var tmp = i.elem();
tmp->value->delete();
free(tmp->value => i8*);
tmp->value = value->copy();
return;
}
bucket_list = bucket_list->next;
}
if (self->data[hash] => i8* == nil) {
self->data[hash] = bucket<K, V>::__alloc__();
bucket_list = self->data[hash];
bucket_list->pair.key = key->copy();
bucket_list->pair.value = value->copy();
bucket_list->next = nil => bucket<K, V>*;
self->size += 1 => u64;
return;
}
bucket_list = self->data[hash];
while (bucket_list->next => i8* != nil) {
bucket_list = bucket_list->next;
}
bucket_list->next = bucket<K, V>::__alloc__();
bucket_list = bucket_list->next;
bucket_list->pair.key = key->copy();
bucket_list->pair.value = value->copy();
bucket_list->next = nil => bucket<K, V>*;
var tmp_pair = pair<K, V> {
key: key,
value: value
};
// do copy in insert method
bucket->insert(tmp_pair.__ptr__());
self->size += 1 => u64;
}
}
@ -139,7 +113,7 @@ impl hashmap<K, V> {
pub struct hashmap_iter<K, V> {
map: hashmap<K, V>*,
bucket_index: u64,
bucket_list: bucket<K, V>*
bucket_list_iter: list_iter<pair<K, V>>
}
impl hashmap_iter<K, V> {
@ -147,50 +121,49 @@ impl hashmap_iter<K, V> {
var res = hashmap_iter<K, V> {
map: map,
bucket_index: 0 => u64,
bucket_list: nil => bucket<K, V>*
bucket_list_iter: map->data[0].iter()
};
for (var i = 0 => u64; i < map->data_capacity; i += 1 => u64) {
var bucket_list = map->data[i];
if (bucket_list => i8* != nil) {
res.bucket_index = i;
res.bucket_list = bucket_list;
break;
while (res.bucket_list_iter.is_end()) {
res.bucket_index += 1 => u64;
if (res.bucket_index >= map->data_capacity) {
return res;
}
res.bucket_list_iter = map->data[res.bucket_index].iter();
}
return res;
}
pub func next(self) -> hashmap_iter<K, V> {
var res = hashmap_iter<K, V> {
if (!self->bucket_list_iter.is_end()) {
self->bucket_list_iter = self->bucket_list_iter.next();
}
while (self->bucket_list_iter.is_end()) {
self->bucket_index += 1 => u64;
if (self->bucket_index >= self->map->data_capacity) {
break;
}
self->bucket_list_iter = self->map->data[self->bucket_index].iter();
}
return hashmap_iter<K, V> {
map: self->map,
bucket_index: self->bucket_index,
bucket_list: nil => bucket<K, V>*
bucket_list_iter: self->bucket_list_iter,
};
if (self->bucket_list->next => i8* != nil) {
res.bucket_list = self->bucket_list->next;
return res;
}
for (var i = self->bucket_index + 1 => u64; i < self->map->data_capacity; i += 1 => u64) {
var bucket_list = self->map->data[i];
if (bucket_list => i8* != nil) {
res.bucket_index = i;
res.bucket_list = bucket_list;
return res;
}
}
return res;
}
pub func is_end(self) -> bool {
return self->bucket_list => i8* == nil;
return self->bucket_index >= self->map->data_capacity &&
self->bucket_list_iter.is_end();
}
pub func key(self) -> K* {
return self->bucket_list->pair.key;
return self->bucket_list_iter.elem()->key;
}
pub func value(self) -> V* {
return self->bucket_list->pair.value;
return self->bucket_list_iter.elem()->value;
}
}

View File

@ -37,7 +37,7 @@ func test_hashmap() {
var map = hashmap<str, str>::instance();
var stored = vec<str>::instance();
for (var i = 0; i < 32; i += 1) {
for (var i = 0; i < 128; i += 1) {
var num = rand() % (4096 => i32);
itoa(num => i64, buff, 10);
var k = str::instance();
@ -51,7 +51,7 @@ func test_hashmap() {
v.delete();
}
for (var i = 0; i < 32; i += 1) {
for (var i = 0; i < 128; i += 1) {
var key = stored.get(i => u64);
if (map.has(key)) {
io::stdout().out("[").green().out("test").reset().out("] hashmap ");